Primeiros passos com React Hooks — useReducer.

João Paulo Nobrega (JP)
4 min readJun 22, 2019

--

Nessa série de artigos vamos falar sobre os novos hooks disponibilizados na versão 16.8 do React.

Artigo: useState
Artigo: useEffect

Hoje o assunto é useReducer!

Introdução

Quem ainda não se perdeu nos “emaranhados” do Redux que atire a primeira pedra! Por isso entender o flow do Redux as vezes não é o suficiente, os apps tendem a crescer e perder seu padrão quando passam nas mãos de vários desenvolvedores.
UseReducer é uma forma mais limpa e menos verbosa de implementar um redutor para desacoplar a lógica de “ações” do seu componente.

Comparações

Resumidamente o flow do Redux em imagem:

Redux Flow

Quando tomamos a decisão de implementar o flow do Redux nas nossas aplicações React, logo nos vem em mente toda aquela implementação de store/actions/reducers/combineReducers/middlewares/mapStateToProps/mapDispatchToProps, etc ….

Implementar toda essa “infraestrutura” faz sentido quando queremos descentralizar a forma de como as ações são executadas nos nossos componentes.

UseReducer é uma forma de implementar um redutor sem precisamos de toda a implementação que o Redux traz com ele.

UseReducer recebe 3 argumentos:

1° reducer do tipo (state, action) => newState.
2° initialArg, o state inicial para aquele redutor.
3° (opcional) uma função “init” que vai setar o state inicial para init(initialArg).

Exemplo:const [ state, dispatch ] = useReducer(reducer, initialArg, init);

UseReducer retorna um array com o state para aquele redutor e o dispatch (se você já usou Redux sabe como isso funciona).

Exemplo

Agora que já entendemos como useReducer funciona vamos voltar para nosso componente de Login e fazer um pequeno refactory nele.

Estado atual do nosso componente.

LoginComponent with Hooks

Olhando para nosso componente vamos imaginar que queremos descentralizar as ações do usuário para um redutor.

Em nosso redutor vamos separar em duas actions.

FETCHED_USER: Que ficará responsável por atualizar o state “user ” caso o usuário seja encontrado.
USER_LOGIN: Que será responsável pelo login do usuário.

Com isso, nosso redutor ficará assim.

user-reducer.js

Note que nosso redutor expõem duas constantes. O state inicial (initialUserState) e o próprio redutor (reducerUser).
O método postUserLogin é responsável por chamar o serviço (API) e fazer o login do usuário (aqui vamos focar no uso do redutor).

Agora com as ações criadas vamos implementar o redutor em nosso componente de Login.

Implementation useReducer

Agora, vamos olhar as modificações que fizemos;

Line 5: Trocamos nosso useState que guardava os dados do usuário pela implementação do nosso redutor. Agora temos userState que guarda todas as informações do redutor do usuário e o dispatch responsável por despachar as ações.
Line 6: Estamos fazendo um destructuring do state do redutor retirando apenas as props que iremos usar.
Prop USER: guarda as informações do usuário recebidas do serviço.
Prop fetchedUser: guarda a informação, que a busca do usuário no serviço foi realizada com sucesso.
Line 13: Dentro do nosso efeito de renderização depois de receber o user caso seja encontrado vamos chamar o dispatch com a action ‘FETCHED_USER’ que atualizará o user.
Line 30: Dentro da nossa função handleSubmit vamos chamar o dispatch com action ‘USER_LOGIN’ que irá criar a autenticação do user.

Vantagens

Note que agora desacoplamos a lógica de ações do nosso componente, com isso, o componente pode ganhar nossas actions sem perder seu padrão. Essa abordagem te ajuda a deixa seu componente mais limpo e com pouco/nenhuma manipulação de estado.

Nem tudo são flores …

O bom uso de redutores vai te ajudar a deixar os componentes mais limpos, mais é importante entender que desacoplar ações pode deixa seu APP mais complexo, por isso, quando usar redutores a organização é fundamental para manter o padrão para novas implementações de redutores e actions.
Eu costumo dizer que quanto mais simples melhor, com uma boa organização useReducer vai te ajudar a ter componentes de fácil manutenção e entendimento.

Conclusão

Esse é um dos hooks que mais gosto. O principio de responsabilidade única é algo que corre na veia (e isso não é um particularidade do backend)!

UseReducer faz com que os componentes tenham apenas a responsabilidade de renderizar o que nós solicitamos, toda a parte de lógica de estado fica por conta do redutor de forma simples e desacoplada.
Aqui não se torna necessário todo o conhecimento no flow do Redux (apesar de muito valido), com isso a curva para implementar um redutor é quase zero.

Você pode combinar o uso de useReducer com useContext para ter state e dispatch globais, vamos falar mais disso no próximo artigo.

No próximo artigo da serie vamos falar um pouco sobre useContext.

Referências

--

--

João Paulo Nobrega (JP)

JP is a Senior Fullstack Software Engineer and C#/JavaScript/React specialist with over 15 years experience in industry