- npx create-react-app my-app-redux;
- cd my-app-redux
- npm install redux react-redux;
- npm install react-router-dom@v5 (caso utilizar rotas)
- npm install redux-thunk (caso utilizar operações assíncronas no redux)
- npm install --save redux-devtools-extension (caso utilizar operações assíncronas no redux)
Criar dentro do diretório src:
- diretório actions;
- diretório reducers;
- diretório store;
- criar os arquivos para cada diretório segundo funcionalidade e arquivo index.js (store obrigatório);
- diretório components;
- diretório pages(opcional)
- Inserir o provider(normalmente no componente index.js)
import { Provider } from 'react-redux';
import store from './store';
ReactDOM.render(
<React.StrictMode>
<Provider store={store} >
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
- Inserir o BrowserRouter (caso utilizar rotas)
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import store from './store';
ReactDOM.render(
<React.StrictMode>
<Provider store={store} >
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
- Inserir o switch e as routes
import { Switch, Route } from 'react-router-dom';
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/explore" component={Explore} />
</Switch>),
- Importar rootReducer do caminho ./reducers/index.js e criar store no caminho ./store/index.js
import { createStore, combineReducers } from 'redux';
import carReducer from './carReducer';
import trafficReducer from './trafficReducer';
const rootReducer = combineReducers({
carReducer,
trafficReducer});
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
Caso haver operações assíncronas, realizar a criação do state da seguinte forma:
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import carReducer from './carReducer';
import trafficReducer from './trafficReducer';
const rootReducer = combineReducers({
carReducer,
trafficReducer});
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)));
- Criar os reducers e o rootReducer(caso necessário, lembrando que é uma boa prática usar o combineReducers)
const Initial_State = [];
function registerReducer(state = Initial_State, action) {
switch (action.type) {
case 'ADD_REGISTER':
return [...state, action.data];
case 'DELETE_REGISTER':
return state.filter(register => register !== action.value);
default:
return state;
}
}
export default registerReducer;
- Criar as actions segundo casa funcionalidade da aplicação
export const addRegister = value => ({ type: 'ADD_REGISTER', data: value });
export const deleteRegister = value => ({ type: 'DELETE_REGISTER', value });
export const login = value => ({ type: 'LOGIN', value });
Segue abaixo uma action assíncrona:
const requestMovies = () => ({
type: REQUEST_MOVIES});
const receiveMovies = (movies) => ({
type: RECEIVE_MOVIES,
movies});
export function fetchMovies() {
return (dispatch) => { // thunk declarado
dispatch(requestMovies());
return fetch('alguma-api-qualquer.com')
.then((response) => response.json())
.then((movies) => dispatch(receiveMovies(movies)));
};
}
Caso haja a necessidade da utilização do redux nos components ou pages, utilize:
- a função mapStateToProps: receber informações do state do redux;
const mapStateToProps = state => ({
registers: state.NOME_DO_REDUCER(caso utilizou o combineReducers).PROPRIEDADE(caso necessário),
userLogin: state.loginReducer});
- a função mapDispatchToProps
const mapDispatchToProps = dispatch => ({
delete: (parâmetro exigido pela action) => dispatch(ACTION(parâmetro exigido pela action))});
- connect: permite a conexão junto ao state. Caso utilize alguma das funções acima, seu uso é obrigatório
import { connect } from 'react-redux';
export default connect(mapStateToProps, mapDispatchToProps)(COMPONENT);
Check List REDUX