Começando com o Redux: Aprenda pelo exemplo

O Redux ajuda você a gerenciar o estado configurando o estado em um nível global. No tutorial anterior, demos uma boa olhada na arquitetura Redux e nos componentes integrais do Redux, como ações, criadores de ação, loja e redutores.

Neste segundo post da série, vamos reforçar nossa compreensão do Redux e construir sobre o que já sabemos. Começaremos criando um aplicativo Redux realista—uma lista de contatos—que é mais complexo do que um contador básico. Isso o ajudará a fortalecer sua compreensão do conceito de armazenamento único e vários redutores que apresentei no tutorial anterior. Depois, falaremos sobre vincular seu estado Redux a um aplicativo React e as melhores práticas que você deve considerar ao criar um projeto do zero.

No entanto, tudo bem se você não leu o primeiro post – você ainda poderá acompanhar desde que conheça o básico do Redux. O código do tutorial está disponível no repositório e você pode usá-lo como ponto de partida.

Criando uma lista de contatos usando o Redux

Vamos construir uma lista de contatos básica com os seguintes recursos:

  • exibir todos os contatos
  • procurar contatos
  • buscar todos os contatos do servidor
  • adicionar um novo contato
  • empurrar os novos dados de contato para o servidor

Veja como ficará nossa aplicação:

Começando com Redux Visualização Final da Lista de ContatosComeçando com Redux Visualização Final da Lista de ContatosComeçando com Redux Visualização Final da Lista de Contatos
Produto final — Visualização da lista de contatos
Introdução ao Redux Visão final do formulário de contatoIntrodução ao Redux Visão final do formulário de contatoIntrodução ao Redux Visão final do formulário de contato
Produto final — Adicionar visualização de contato

Cobrir tudo em um trecho é difícil. Portanto, neste post, vamos nos concentrar apenas na parte Redux de adicionar um novo contato e exibir o contato recém-adicionado. Do ponto de vista do Redux, estaremos inicializando o estado, criando a loja, adicionando redutores e ações, etc.

No próximo tutorial, aprenderemos como conectar React e Redux e despachar ações Redux de um front-end React. Na parte final, mudaremos nosso foco para fazer chamadas de API usando Redux. Isso inclui buscar os contatos do servidor e fazer uma solicitação do servidor ao adicionar novos contatos. Além disso, também criaremos um recurso de barra de pesquisa que permite pesquisar todos os contatos existentes.

Criar um esboço da árvore de estado

Você pode baixar o aplicativo de demonstração react-redux do meu repositório GitHub. Clone o repositório e use o v1 ramo como ponto de partida. o v1 branch é muito semelhante ao template create-react-app. A única diferença é que adicionei alguns diretórios vazios para organizar o Redux. Aqui está a estrutura de diretórios.

Alternativamente, você pode criar um novo projeto do zero. De qualquer forma, você precisará ter instalado um clichê básico de reação e redux antes de começar.

É uma boa ideia ter primeiro um esboço da árvore de estado. Na minha opinião, isso vai lhe poupar muito tempo a longo prazo. Aqui está um esboço da árvore de estado possível.

Nossa loja precisa ter duas propriedades—contacts e ui. A propriedade de contatos cuida de todos os estados relacionados a contatos, enquanto a propriedade ui lida com o estado específico da interface do usuário. Não existe uma regra rígida no Redux que impeça você de colocar o ui objeto como um subestado de contacts. Sinta-se à vontade para organizar seu estado de uma maneira que pareça significativa para sua aplicação.

A propriedade de contatos tem duas propriedades aninhadas dentro dela—contactlist e newContact. o contactlist é uma matriz de contatos, enquanto newContact armazena temporariamente os detalhes de contato enquanto o formulário de contato está sendo preenchido. Vou usar isso como ponto de partida para criar nosso incrível aplicativo de lista de contatos.

Como organizar o Redux

O Redux não tem uma opinião sobre como você estrutura sua aplicação. Existem alguns padrões populares por aí e, neste tutorial, falarei brevemente sobre alguns deles. Mas você deve escolher um padrão e ficar com ele até entender completamente como todas as peças estão conectadas.

O padrão mais comum que você encontrará é a estrutura de arquivos e pastas no estilo Rails. Você terá vários diretórios de nível superior como os abaixo:

  • componentes: Um lugar para armazenar os componentes burros do React. Esses componentes não se importam se você está usando o Redux ou não.
  • recipientes: Um diretório para os componentes inteligentes do React que despacham ações para o repositório Redux. A ligação entre redux e react ocorrerá aqui.
  • ações: Os criadores da ação irão para dentro deste diretório.
  • redutores: Cada redutor recebe um arquivo individual e você colocará toda a lógica do redutor nesse diretório.
  • armazenar: A lógica para inicializar o estado e configurar a loja irá aqui.

A imagem abaixo demonstra como nossa aplicação pode ficar se seguirmos este padrão:

Organizando a estrutura de pastas no ReduxOrganizando a estrutura de pastas no ReduxOrganizando a estrutura de pastas no Redux

O estilo Rails deve funcionar para aplicativos de pequeno e médio porte. No entanto, quando seu aplicativo cresce, você pode considerar a abordagem de estilo de domínio ou outras alternativas populares que estão intimamente relacionadas ao estilo de domínio. Aqui, cada recurso terá um diretório próprio, e tudo relacionado a esse recurso (domínio) estará dentro dele. A imagem abaixo compara as duas abordagens, estilo Rails à esquerda e estilo domínio à direita.

Comparação de duas técnicas populares para organizar Redux e ReactComparação de duas técnicas populares para organizar Redux e ReactComparação de duas técnicas populares para organizar Redux e React

Por enquanto, vá em frente e crie diretórios para componentes, recipientes, armazenar, redutorese ação. Vamos começar com a loja.

Loja única, vários redutores

Vamos criar um protótipo para a armazenar e a redutor primeiro. Do nosso exemplo anterior, é assim que nossa loja ficaria:

A instrução switch tem três casos que correspondem a três ações que estaremos criando. Aqui está uma breve explicação do que as ações são destinadas.

  • HANDLE_INPUT_CHANGE: esta ação é acionada quando o usuário insere novos valores no formulário de contato.
  • ADD_NEW_CONTACT: esta ação é despachada quando o usuário envia o formulário.
  • TOGGLE_CONTACT_FORM: esta é uma ação de interface do usuário que se encarrega de mostrar/ocultar o formulário de contato.

Embora essa abordagem ingênua funcione, à medida que o aplicativo cresce, o uso dessa técnica terá algumas deficiências.

  1. Estamos usando um único redutor. Embora um único redutor pareça bom por enquanto, imagine ter toda a sua lógica de negócios sob um redutor muito grande.
  2. O código acima não segue a estrutura do Redux que discutimos na seção anterior.

Para corrigir o problema do redutor único, o Redux tem um método chamado combineReducers que permite criar vários redutores e depois combiná-los em uma única função de redução. A função combineReducers melhora a legibilidade. Então, vou dividir o redutor em dois – um contactsReducer e um uiReducer.

No exemplo acima, createStore aceita um opcional segundo argumento que é o estado inicial. No entanto, se vamos dividir os redutores, podemos mover todo o initialState para um novo local de arquivo, digamos redutores/initialState.js. Vamos então importar um subconjunto de initialState em cada arquivo redutor.

Dividindo o redutor

Vamos reestruturar nosso código para corrigir os dois problemas. Primeiro, crie um novo arquivo chamado store/createStore.js e adicione o seguinte código:

Em seguida, crie um redutor de raiz em redutores/index.js do seguinte modo:

Finalmente, precisamos criar o código para o contactsReducer e uiReducer.

redutores/contatosReducer.js

redutores/uiReducer.js

Ao criar redutores, sempre tenha em mente o seguinte: um redutor precisa ter um valor padrão para seu estado e sempre precisa retornar algo. Se o redutor não seguir esta especificação, você receberá erros.

Já que cobrimos muito código, vamos dar uma olhada nas mudanças que fizemos com nossa abordagem:

  1. o combineReducers chamada foi introduzida para unir os redutores de divisão.
  2. O estado do ui objeto será tratado por uiReducer e o estado dos contatos pelo contactsReducer.
  3. Para manter os redutores puros, foram utilizados operadores de espalhamento. A sintaxe de três pontos faz parte do operador de propagação. Se você não estiver confortável com a sintaxe de propagação, considere usar uma biblioteca como Immutability.js.
  4. O valor inicial não é mais especificado como um argumento opcional para createStore. Em vez disso, criamos um arquivo separado para ele chamado inicialState.js. Estamos importando initialState e, em seguida, definindo o estado padrão fazendo state = initialState.ui.

Inicialização do estado

Aqui está o código para o redutores/initialState.js Arquivo.

Ações e criadores de ações

Vamos adicionar algumas ações e criadores de ações para adicionar alterações no formulário de manipulação, adicionar um novo contato e alternar o estado da interface do usuário. Se você se lembra, criadores de ação são apenas funções que retornam uma ação. Adicione o seguinte código em actions/index.js.

Cada ação precisa retornar uma propriedade de tipo. O tipo é como uma chave que determina qual redutor é invocado e como o estado é atualizado em resposta a essa ação. A carga útil é opcional e você pode chamá-la como quiser.

No nosso caso, criamos três ações.

o TOGGLE_CONTACT_FORM não precisa de uma carga porque toda vez que a ação é acionada, o valor de ui.isContactFormHidden fica alternado. As ações com valor booleano não exigem uma carga útil.

o HANDLE_INPUT_CHANGE A ação é acionada quando o valor do formulário é alterado. Então, por exemplo, imagine que o usuário está preenchendo o campo de e-mail. A ação recebe então "email" e "[email protected]" como entradas, e a carga útil entregue ao redutor é um objeto que se parece com isso:

O redutor usa essas informações para atualizar as propriedades relevantes do newContact Estado.

Ações de despacho e assinatura da loja

O próximo passo lógico é despachar as ações. Uma vez que as ações são despachadas, o estado muda em resposta a isso. Para despachar ações e obter a árvore de estado atualizada, o Redux oferece certas ações de armazenamento. Eles são:

  • dispatch(action): despacha uma ação que pode potencialmente acionar uma mudança de estado.
  • getState(): Retorna a árvore de estado atual do seu aplicativo.
  • subscriber(listener): um ouvinte de alteração que é chamado toda vez que uma ação é despachada e alguma parte da árvore de estado é alterada.

Dirija-se ao index.js arquivo e importe o configureStore função e as três ações que criamos anteriormente:

A seguir, crie um store object e adicione um listener que registra a árvore de estado toda vez que uma ação é despachada:

Por fim, despache algumas ações:

Se tudo estiver funcionando corretamente, você deverá ver isso no console do desenvolvedor.

Loja Redux sendo logada no console do desenvolvedorLoja Redux sendo logada no console do desenvolvedorLoja Redux sendo logada no console do desenvolvedor

É isso! No console do desenvolvedor, você pode ver a loja do Redux sendo registrada, para ver como ela muda após cada ação.

Resumo

Criamos um aplicativo Redux básico para nosso incrível aplicativo de lista de contatos. Aprendemos sobre redutores, dividindo redutores para tornar nossa estrutura de aplicativo mais limpa e escrevendo ações para alterar a loja.

No final do post, nos inscrevemos na loja usando o store.subscribe() método. Tecnicamente, esta não é a melhor maneira de fazer as coisas se você for usar React com Redux. Existem maneiras mais otimizadas de conectar o front-end de reação ao Redux. Abordaremos isso no próximo tutorial.

Deixe um comentário

O seu endereço de e-mail não será publicado.