Quem tem medo do Redux?

Wesley Monaro
caquicoders
Published in
6 min readJan 7, 2019

Sempre que ouço alguém que não conhece o redux, e quer estuda-lo, ouço coisas como:

"Nossa, ouvi dizer que o redux é difícil", ou "Já estou apanhando agora, imagina quando ver o redux" e coisas do tipo.

Realmente, o redux não é algo tão simples de entender, mas também não é esse monstro que parece/dizem.

Primeiramente, pra que serve o redux?

Ao contrário do que parece, (eu pensava que era, inclusive), o redux não precisa ser usado exclusivamente no ReactJS. Comumente você vê projetos ReactJS usando redux, mas ele pode ser usado em qualquer aplicação JS.

Vou tentar ser didático, pra facilitar o entendimento aqui.

Imagine uma empresa que tem um almoxarifado. Todos os materiais da empresa ficam centralizados lá. Cada departamento tem o seu estoque interno, e não podem "emprestar" materiais para outro setor. Quando determinado material acaba, ou não é suficiente, alguém vai até o almoxarifado buscar.

Processo simples, né?

Agora imagine que, você tem uma aplicação, com diversos componentes. Cada componente tem um estado local (state) que não compartilha informações com outros componentes, e que em certos momentos, precisa buscar informações em um repositório central.

Hey, calma aí! Parece familiar:

Departamento -> Componente
Material -> Estado local (state)
Almoxarifado -> Redux

Ok, o conceito é fácil. Vamos evoluir um pouco mais.

Dentro do almoxarifado, o almoxarife é responsável por receber a requisição do material, faz os procedimentos necessários, e a repassa para o estagiário atualizar o estoque dando baixa no material (ou aumentando o estoque em caso de entradas). O material então é entregue no seu departamento.

Na sua aplicação, você faz uma requisição para uma action, que executa uma função. O resultado dela, é repassado para um reducer, que atualiza o estado global.

Almoxarife -> action
Estagiário -> reducer

Legal! Pra complementar, vamos complicar um pouco.

O material que você pediu não está no estoque. Será necessário realizar um pedido de compra no site do fornecedor, e aguardar chegar. Quando for entregue, o estoque será atualizado e seu departamento receberá o material.

Na sua aplicação, você precisa de uma informação que é dada por uma API. Você faz a requisição para a action, a action realizará uma outra requisição para essa API (através de um middleware), e quando a informação voltar, ela irá repassar para o reducer, que atualizará o estado.

Pedido de compra -> Requisição a API
Aguardar chegar -> Promise
Site do fornecedor -> Middleware (Normalmente Redux Thunk ou Saga, mas existem outros).

Viu, não é tão complicado!

Ok. Agora vamos ver um pouco de código.

A ideia é mostrar como podemos criar a nossa store de forma simples, usando o Redux Thunk. Deixaremos o Redux Saga para outro post ;)

Primeiro iremos criar o projeto rodando o comando:

create-react-app teste-redux

Será criada uma estrutura como essa:

Na pasta src, deixe apenas os arquivos App.js e index.js. Exclua o resto. Altere os dois para que fiquem dessa forma:

Se rodarmos o comando npm start, uma página será aberta no navegador mostrando "Teste Redux".

Agora, iremos instalar as dependências para usarmos o redux e o redux thunk.

Rode no terminal:

npm i redux react-redux redux-thunk

Ainda na src, vamos criar 4 arquivos:

  • appReducers.js
  • store.js
  • action.js
  • reducer.js

Vamos um por um, nessa ordem:

No action.js, criaremos uma função que retorna um dispatch. Esse cara quem controla é o Redux Thunk. Todo o código de requisição a API precisa estar dentro desse dispatch. No exemplo não vamos consumir API, apenas como exemplo.

Na linha 5, chamamos o método dispatch passando um objeto com 2 parâmetros:

  • type: Identificador dessa função. Através desse parâmetro o reducer saberá qual valor do store ele deve atualizar.
  • payload: É o valor que queremos passar. Pode ser de qualquer tipo.

No reducer.js, iniciamos uma constante que será o nosso estado inicial. Estou iniciando com um array vazio, chamado materiais.

Na linha 5, chamo uma função que recebe dois parâmetros, um estado, e um action. Caso o estado ainda não exista (quando a aplicação é iniciada), atribuímos o estado inicial para ela.

Na linha 6 fazemos um switch case pra validar qual o tipo de informação estamos lidando. Lembra que passamos na action esse valor como COMPRA_MATERIAL? Pois então, é agora que o reducer vai receber essa informação e verificar o que deve ser feito, que é o que fazemos na linha 8. Estamos atualizando o estado, usando as informações que já existem (fazendo o spread de state), e incluímos esse novo material no array que já temos (também usando o spread).

Caso nenhuma condição satisfaça esse switch case, ele simplesmente retorna o estado.

OBS- É muito importante esse default no final, e já vou explicar por que.

No appReducers.js, iremos unir todos os reducers da nossa aplicação. Nesse exemplo usamos apenas 1, mas em aplicações maiores você terá vários reducers. Repare na linha 4 o método combineReducers. Aqui conseguimos entender porque precisamos de swtich cases nos reducers. Quando uma action chama o dispatch, TODOS os reducers são notificados, mas apenas as condições que você criou terão efeito.

E por último, vamos criar nosso store. Importamos o middleware Redux Thunk e nossos reducers combinados. Na linha 4 importamos 2 caras importantíssimos do pacote redux, que são applyMiddleware e createStore. Os nomes já são auto-explicativos.

O applyMiddleware espera como parâmetro os middlewares que vamos usar (declarado na linha 6).

O createStore espera os nossos reducers combinados, e também nossos middlewares. Por isso na linha 8 já criamos tudo isso com apenas uma instrução.

Por fim, precisamos fazer uma pequena alteração no nosso App.js:

Aqui nós importamos o Provider do react-redux, e nosso store. Como elemento "container", usamos o Provider, passando nosso objeto store como propriedade. Com isso, temos uma aplicação rodando com redux \o/

Execute o comando npm start e veja o resultado.

Não mudou nada! hehe

Mas acredite em mim, isso é bom. Significa que toda nossa store foi criada, o middleware foi aplicado, e temos o redux pronto para usarmos. Vamos fazer isso?

A ideia é apenas criar um botão que irá chamar o método na nossa action, e aí vamos ver a criança em ação.

Vamos mudar a estrutura do nosso App.js. deixe dessa forma:

O que fizemos foi deixar dentro do store apenas um componente que chamamos de Home. Esse será o nosso componente principal. Portanto, na pasta src crie o home.js:

Nas linhas 2 e 4 importamos o método connect do react-redux, e o nosso método compraMateriais, que está na nossa action.

Na linha 8, fazemos a desestruturação para recuperar materiais e compraMateriais, que estão nas props do componente.

Na linha 13 criamos um botão que chama esse método.

Na linha 16, criamos um map para percorrer toda nossa lista de materiais. Exibimos o nome e a quantidade dentro de um <li>

Agora, temos 2 métodos que são responsáveis por recuperar os dados do redux.

Na linha 27 criamos o mapStateToProps, que recupera um valor do store, e atribui para as props desse componente.

O mesmo acontece na linha 31, mas esse recupera os métodos que criamos nas actions.

Por fim, na linha 35 chamamos o método connect, que une os dois em apenas um componente, e no final do arquivo o exportamos.

Com isso teremos a aplicação rodando, e para cada vez que o botão é clicado, um material é adicionado na lista.

Sei que parece complicado de início, mas depois de alguns actions e reducers, as coisas ficam mais claras.

IMPORTANTE- Você NÃO precisa usar TUDO no redux. Você pode continuar usando o state da classe para valores locais, como dados de formulário por exemplo.

Caso queira, o código do projeto pode ser encontrado aqui.

Espero que tenham gostado. Até o próximo artigo ;)

--

--

Wesley Monaro
caquicoders

Senior System Analyst @rchlo, Developer and Partner @ONNZE.com, and Community Manager @caquicoders