Skip to content

Commit

Permalink
Refactoring application to use redux-saga and redux-actions lib
Browse files Browse the repository at this point in the history
  • Loading branch information
Luiz Felicio committed Dec 19, 2019
1 parent c1707b8 commit 3547fff
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 139 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.0",
"redux": "^4.0.4",
"redux-actions": "^2.6.5",
"redux-devtools-extension": "^2.13.8",
"redux-saga": "^1.1.3",
"redux-thunk": "^2.3.0",
"styled-components": "^4.4.1"
},
Expand Down
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="PokeCardéx using PokeTCG API"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
<title>PokeCardéx</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
Binary file removed public/logo192.png
Binary file not shown.
Binary file removed public/logo512.png
Binary file not shown.
14 changes: 2 additions & 12 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "PokeCardéx",
"name": "PokeCardéx using PokeTCG API",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
Expand Down
2 changes: 0 additions & 2 deletions public/robots.txt

This file was deleted.

11 changes: 6 additions & 5 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@ import { BrowserRouter as Router } from 'react-router-dom';
import Header from './components/Header';
import RoutesContainer from './Routes';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchCards, fetchCardByPokeName } from './store/ducks/cards';
import { actions as cardActions } from './store/ducks/cards';

import './app.css';

function App({
loading, cards, fetchCards, fetchCardByPokeName,
loading, cards, fetchCards,
}) {
useEffect(() => {
fetchCards();
}, []);

const doSearchPokemon = (input) => {
fetchCardByPokeName(input);
fetchCards(input);
};

return (
Expand All @@ -34,6 +33,8 @@ const mapStateToProps = (state) => ({
cards: state.cards,
});

const mapDispatchToProps = (dispatch) => bindActionCreators({ fetchCards, fetchCardByPokeName }, dispatch);
const mapDispatchToProps = {
fetchCards: cardActions.cards.fetchCards.request,
};

export default connect(mapStateToProps, mapDispatchToProps)(App);
59 changes: 0 additions & 59 deletions src/api/mock.json

This file was deleted.

8 changes: 4 additions & 4 deletions src/components/Header/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { useHistory } from 'react-router-dom';

import Button from '../Button';
import Input from '../TextInput';
Expand Down Expand Up @@ -31,8 +31,9 @@ const StyledContainer = styled.div`
}
`;

const Header = ({ doSearchPokemon, history }) => {
const Header = ({ doSearchPokemon }) => {
const [input, setInput] = useState('');
const history = useHistory();

const handleSearch = () => {
if (input) {
Expand Down Expand Up @@ -68,7 +69,6 @@ const Header = ({ doSearchPokemon, history }) => {

Header.propTypes = {
doSearchPokemon: PropTypes.func.isRequired,
history: PropTypes.objectOf(Object).isRequired,
};

export default withRouter(Header);
export default Header;
147 changes: 94 additions & 53 deletions src/store/ducks/cards.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { createActions, handleActions } from 'redux-actions';
import { call, put, takeLatest } from 'redux-saga/effects';
import api from '../../api';


/** ********************************
* TYPES
******************************** */
export const Types = {
FETCH_CARDS_PENDING: 'FETCH_CARDS_PENDING',
FETCH_CARDS_SUCCESS: 'FETCH_CARDS_SUCCESS',
FETCH_CARDS_ERROR: 'FETCH_CARDS_ERROR',
};
// export const Types = {
// FETCH_CARDS_REQUEST: 'FETCH_CARDS_REQUEST',
// FETCH_CARDS_PENDING: 'FETCH_CARDS_PENDING',
// FETCH_CARDS_SUCCESS: 'FETCH_CARDS_SUCCESS',
// FETCH_CARDS_ERROR: 'FETCH_CARDS_ERROR',
// };

/** ********************************
* STATE
******************************** */
const INITAL_STATE = {
const INITIAL_STATE = {
cards: [],
loading: false,
error: false,
Expand All @@ -21,68 +25,105 @@ const INITAL_STATE = {
/** ********************************
* ACTIONS
******************************** */
export const ActionCreators = {
fetchCardsPending: () => ({
type: Types.FETCH_CARDS_PENDING,
}),

fetchCardsSuccess: (payload) => ({
type: Types.FETCH_CARDS_SUCCESS,
payload,
}),

fetchCardsFailure: (payload) => ({
type: Types.FETCH_CARDS_ERROR,
payload,
}),
};

/** ********************************
* ACTIONS (THUNK)
******************************** */

export const fetchCards = () => (dispatch) => {
dispatch(ActionCreators.fetchCardsPending());
api.get('/cards')
.then((response) => dispatch(ActionCreators.fetchCardsSuccess(response.data.cards)))
.catch((error) => dispatch(ActionCreators.fetchCardsFailure(error)));
};

export const fetchCardByPokeName = (input) => (dispatch) => {
dispatch(ActionCreators.fetchCardsPending());
api.get(`/cards?name=${input}`)
.then((response) => dispatch(ActionCreators.fetchCardsSuccess(response.data.cards)))
.catch((error) => dispatch(ActionCreators.fetchCardsFailure(error)));
};
const requestPattern = { REQUEST: undefined, SUCCESS: undefined, FAILURE: undefined };

export const actions = createActions({
cards: {
FETCH_CARDS: requestPattern,
},
});

/** ********************************
* REDUCER
******************************** */
export const reducer = (state = INITAL_STATE, action) => {
switch (action.type) {
case Types.FETCH_CARDS_PENDING:
export const reducer = handleActions({
[actions.cards.fetchCards.request](state) {
return {
...state,
loading: true,
error: false,
};
case Types.FETCH_CARDS_SUCCESS:
},
[actions.cards.fetchCards.success](state, { payload }) {
return {
...state,
cards: action.payload,
cards: payload,
loading: false,
error: false,
};

case Types.FETCH_CARDS_ERROR:
},
[actions.cards.fetchCards.failure]() {
return {
...state,
cards: [],
loading: false,
error: true,
};
},
}, INITIAL_STATE);

// export const ActionCreators = {
// fetchCardsRequest: (payload) => ({
// type: Types.FETCH_CARDS_REQUEST,
// payload,
// }),

// fetchCardsSuccess: (payload) => ({
// type: Types.FETCH_CARDS_SUCCESS,
// payload,
// }),

// fetchCardsFailure: (payload) => ({
// type: Types.FETCH_CARDS_ERROR,
// payload,
// }),
// };

default:
return state;
/** ********************************
* (SAGA)
******************************** */

function* fetchCards(action) {
try {
let response;
if (action.payload) {
response = yield call(api.get, `/cards?name=${action.payload}`);
} else {
response = yield call(api.get, '/cards');
}
yield put(actions.cards.fetchCards.success(response.data.cards));
} catch (error) {
yield put(actions.cards.fetchCards.failure(error));
}
};
}

export function* saga() {
yield takeLatest(actions.cards.fetchCards.request, fetchCards);
}

/** ********************************
* REDUCER
******************************** */
// export const reducer = (state = INITAL_STATE, action) => {
// switch (action.type) {
// case Types.FETCH_CARDS_REQUEST:
// return {
// ...state,
// loading: true,
// error: false,
// };
// case Types.FETCH_CARDS_SUCCESS:
// return {
// ...state,
// cards: action.payload,
// loading: false,
// error: false,
// };

// case Types.FETCH_CARDS_ERROR:
// return {
// cards: [],
// loading: false,
// error: true,
// };

// default:
// return state;
// }
// };
11 changes: 9 additions & 2 deletions src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import { reducer as cardsReducer } from './ducks/cards';
import thunk from 'redux-thunk';

const middlewares = [thunk];
import sagas from './sagas';


const sagaMiddleware = createSagaMiddleware();

const middlewares = [sagaMiddleware];

const store = createStore(
cardsReducer,
Expand All @@ -12,4 +17,6 @@ const store = createStore(
),
);

sagaMiddleware.run(sagas);

export default store;
7 changes: 7 additions & 0 deletions src/store/sagas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { fork } from 'redux-saga/effects';

import { saga as cardSaga } from './ducks/cards';

export default function* rootSaga() {
yield fork(cardSaga);
}
Loading

0 comments on commit 3547fff

Please sign in to comment.