Redux

Uso do Redux

Instalação

Instalação do Redux no React $ yarn add redux react-redux

Configuração

Arquivo /src/store/index.js

import { createStore } from 'redux';
const store = createStore();
export default store;

Arquivo src/App.js

Importação do Provider do react-redux e do método store criado anteriormente

import { Provider } from 'react-redux';
import store from './store';

Envolver todos os componentes com o método Provider passando o atributo store

function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Header />
<Routes />
<GlobalStyle />
</BrowserRouter>
</Provider>
);
}

ATENÇÃO!

O arquivo src/store/index.js necessita de um reducer para funcionar.

Criação do Reducer em src/store/modules/cart/reducer.js

export default function cart() {
return [];
}

Exemplo do arquivo store com com um Reducer

import { createStore } from 'redux';
import reducer from './modules/cart/reducer';
const store = createStore(reducer);
export default store;

Múltiplos reducers

Arquivo src/store/modules/rootReducer.js

import { combineReducers } from 'redux';
import cart from './cart/reducer';
export default combineReducers({
cart,
});

Arquivo src/store/index.js

import { createStore } from 'redux';
import rootReducer from './modules/rootReducer';
const store = createStore(rootReducer);
export default store;

Conexões e Uso Prático

Importação em uma página com componentes

Importação do connect do react-redux

import { connect } from 'react-redux';

Novo modelo de exportação

export default connect()(Home);

Adicionando uma action em um componente

O botão:

<button
type="button"
onClick={() => this.handleAddProduct(product)}
>

A função handleAddProduct():

handleAddProduct = product => {
const { dispatch } = this.props;
dispatch({
type: 'ADD_TO_CART', // O dispatch é quem dispara a função e é acessível graças ao connect
product,
});
};

O reducer:

export default function cart(state = [], action) { // Estado inicial e a ação executada como parâmetro
switch (action.type) {
case 'ADD_TO_CART': // Reducer sendo chamado apenas caso seja o ADD_TO_CART
return [...state, action.product]; // Retornando o estado inicial + o produto chamado naquela action
default:
return state; // Reducer ignorando outras actions que não sejam pertinentes
}
}

Recebendo estado de outros componentes

Exemplo de um cabeçalho de e-commerce.

Importação do connect

import { connect } from 'react-redux';

Passando um objeto na função para conectá-lo com o componente

function Header({ cart }) {
return (
...
)
}

Exportar com o connect passando o estado como um objeto

export default connect(state => ({
cart: state.cart, // O cart de "state.cart" é o cart declarado no rootReducer
}))(Header);

MapStateToProps

Recebe o estado da aplicação e adiciona uma propriedade. Exemplo:

const mapStateToProps = state => ({
cart: state.cart,
});

A função deve se parecer com:

function Cart({ cart }) {
...
}

Exportação:

export default connect(mapStateToProps)(Cart);

MapDispatchToProps

Faz o disparo de uma action e armazena nas propriedades do estado da aplicação.

const mapDispatchToProps = dispatch =>
bindActionCreators(CartActions, dispatch);

O bindActionCreators é importado do redux e o CartActions segue o modelo exemplificado na sessão 5.1.

Exportação:

export default connect(mapStateToProps, mapDispatchToProps)(Cart); // Caso não possua StateToProps, deve ser passado um valor sendo "null"

bindActionCreators

O bindActionCreators serve para organizar melhor o dispatch de actions. Sua importação vem do Redux

import bindActionCreators from 'redux';

É uma função que recebe como primeiro parâmetro as actions e o segundo dispatch:

const mapDispatchToProps = dispatch =>
bindActionCreators(CartActions, dispatch);

Organização de Actions

Exemplo de um arquivo em src/store/modules/cart/actions

Aqui pode ser organizado todas as actions que anteriormente eram enviadas através de uma função dentro do próprio componente.

export function addToCart(product) {
return {
type: '@cart/ADD',
product,
};
}
export function removeFromCart(id) {
return { type: '@cart/REMOVE', id };
}
export function updateAmount(id, amount) {
return {
type: '@cart/UPDATE_AMOUNT',
id,
amount,
};
}

Utilização

Nos exemplos acima são utilizados essas actions com o nome 'CartActions'

Importação

import * as CartActions from '../../store/modules/cart/actions';

Dentro dos parâmetros da função, são passadas as actions existentes no arquivo actions.js que necessitam ser usadas (funções exemplificadas acima):

function Cart({ cart, removeFromCart, updateAmount }) {
...
}