Angular: um exemplo de uso do NGRX

imagem
Este artigo é uma continuação do post "Angular: uma introdução à NGRX".

Exemplo NGRX


No nosso exemplo, haverá uma lista de usuários, uma página de detalhes do usuário e algumas informações de configuração inicial que você deve obter ao iniciar o aplicativo. Vamos implementar alguns threads importantes do NGRX.

Plano de ação:

  1. Instalação da biblioteca
  2. Criando uma estrutura de pastas para armazenamento
  3. Criação de armazenamento e valores iniciais
  4. Criando ações
  5. Criando caixas de engrenagens (redutores)
  6. Criando efeitos
  7. Criando seletores
  8. Configuração final
  9. Usando armazenamento em componentes

Então, vamos fazê-lo ...

Instalação da biblioteca


Vamos usar o Angle Cli para criar o projeto e, em seguida, adicionaremos as bibliotecas do ngrx.

Crie um projeto:

ng new angular-ngrx --style=scss

Adicione as bibliotecas NGRX necessárias:

npm install @ngrx/core @ngrx/store @ngrx/effects @ngrx/store-devtools @ngrx/router-store --save

Instalamos quase todas as bibliotecas do ecossistema ngrx. A maioria deles descreve claramente seu objetivo: núcleo, armazenamento, efeitos, mas há alguns para os quais você pode se perguntar por que eles são necessários?

  • store-devtools - Uma poderosa ferramenta de depuração.
  • router-store - Salva o estado do roteador angular no armazenamento.

Estrutura de pastas para armazenamento


Vamos começar discutindo a estrutura de arquivos do repositório. Essa estrutura de arquivos e toda a configuração de armazenamento devem existir no módulo principal do seu aplicativo, mas no nosso exemplo ele está ausente, portanto o armazenamento existirá no módulo principal do nosso aplicativo (as etapas são quase as mesmas se você fizer isso no módulo principal).

imagem

A estrutura da pasta é uma representação da composição de armazenamento real. Você terá uma pasta principal com o nome "loja" e cinco subpastas que representam cada um dos principais players da loja: "Ações", "Efeitos", "Efeitos", "Redurs", "Seletores" e "Estado".

Criação de armazenamento e valores iniciais


Como mencionamos anteriormente, teremos duas seções principais: nosso aplicativo, usuários e configuração. Para os dois, precisamos criar um estado e um estado inicial e também fazer o mesmo para o estado do aplicativo.

Criamos duas interfaces para definição e configuração do usuário. Também temos um para a resposta HTTP do usuário, é apenas uma matriz IUser.

imagem

imagem

Vamos começar com o estado do usuário (store / state / user.state.ts):

imagem

O que estamos fazendo aqui:

  1. Criamos e exportamos uma interface com uma estrutura de ambiente do usuário.
  2. Fazemos o mesmo com o estado inicial do usuário, que implementa a interface recém-criada.

Para o estado de configuração, fazemos o mesmo (store / states / config.state.ts):

imagem

Finalmente, precisamos gerar o estado do aplicativo (store / states / app.state.ts):

imagem

  1. O estado do aplicativo contém o estado e a configuração do usuário, bem como o estado do roteador.
  2. Em seguida, definimos o estado inicial do aplicativo.
  3. Por fim, exporta a função para obter o estado inicial (vamos usá-lo mais tarde).

Criando ações


Leia a definição de ação que discutimos no artigo anterior .
Precisamos criar ações para usuários e configurações. Vamos começar com as ações do usuário (store / actions / user.actions.ts):

imagem

Vamos percorrer um pouco o código:

  1. Enum, . , , , .
  2. . Action ngrx. , , , .
  3. , , . , , , .

E é tudo ... criar ações é fácil. Vamos ver como são as ações de configuração (store / actions / config.actions.ts):

imagem

nada de novo aqui, você provavelmente agora se sente confortável com tudo o que acontece neste arquivo.

Ótimo, já determinamos o status e as ações ... vamos criar engrenagens!

Criando caixas de velocidades


Certifique-se de ler a definição de caixas de velocidades que discutimos em um artigo anterior .
Teremos caixas de velocidades que respondem a algumas ações, porque outras serão tratadas pelos efeitos que iremos implementar mais tarde.

Vamos precisar de um redutor para usuários e outro para configuração, mas também precisamos gerar redutores de aplicativos. Vamos começar examinando redutores de usuários (store / redurs / user.reducers.ts):

imagem

Vamos discutir a implementação:

  1. Uma declaração redutora recebe um estado e, nesse caso, uma ação do usuário e retorna um IUserState.
  2. Usando a instrução switch, geramos observações para cada tipo de ação possível.
  3. Cada caso retorna um novo objeto, que é o resultado da fusão do estado antigo e do novo valor.
  4. Todas as caixas de velocidades têm um resultado padrão, que simplesmente retorna o estado sem nenhuma alteração.

E é tudo. Você não encontrará mais nada na caixa de velocidades. Vamos dar uma olhada nos redutores de configuração (state / redurs / config.reducers.ts):

imagem

Finalmente, vamos dar uma olhada nos redutores de aplicativos (loja):

imagem

Aqui, adicionamos todos os redutores ao mapa de redutores do aplicativo. Usamos um mapa redutor de ação para verificação de tipo adicional. Mais tarde, forneceremos a esse aplicativo redutores para o módulo de armazenamento.

Adicionar efeitos


Leia a definição de "Efeitos", discutida em um artigo anterior .
Você provavelmente já percebeu que nas caixas de velocidades não processamos todas as ações. Isso ocorre porque vamos lidar com ações perdidas em efeitos, porque essas ações têm efeitos colaterais.

Vamos começar com efeitos personalizados (store / effects / user.effects.ts):

imagem

Muito do que acontece neste arquivo. Vamos tentar explicá-los:

  1. Declaramos nossos efeitos personalizados usando um decorador de injeção.
  2. Declaramos nossos efeitos usando o decorador de efeitos fornecido pelo ngrx / Effects.
  3. Usando as ações fornecidas pelo ngrx / Effects, iniciaremos o pipeline do nosso operador para esse efeito.
  4. A próxima etapa é definir o tipo de ação de efeito usando o operador ofType.
  5. As partes a seguir são os operadores rxjs que usamos para obter o que precisamos (já temos um link para a documentação rxjs neste artigo).
  6. Finalmente, na última declaração, o Effect enviará outra ação.
  7. No construtor, implementamos os serviços que vamos usar, ações para o ngrx / Effects e, neste caso, também o repositório (observe que esta é uma demonstração e obtemos o usuário selecionado da lista de usuários em nosso repositório).

Esta é quase a mesma estrutura que você verá com qualquer efeito. Nesse caso, enviamos apenas uma ação bem-sucedida, mas podemos enviar erros ou qualquer outro estado que desejemos processar em nossos redutores de aplicativos.

Considere os efeitos de configuração (store / effects / config.effects.ts):

imagem

Agora é hora de falar sobre seletores ...


, .
Não faz sentido repetir as fatias do nosso estado em todos os lugares, então vamos criar alguns seletores que podemos reutilizar.

Como sempre, vejamos primeiro os seletores de usuário (store / selectors / user.selectors.ts):

imagem

isso é realmente compreensível, porque não fazemos nenhuma transformação de dados em nossos seletores, mas simplesmente retornamos a fatia da loja referenciada pelo seletor usando a função createSelector a partir do ngrx / store.

O primeiro parâmetro é um fragmento do armazenamento que será usado para receber dados (pode ser uma matriz com várias partes do estado), o segundo parâmetro é uma função anônima que decide o que o seletor retornará.

Vejamos os seletores de configuração (store / selectors / config.selectors.ts):

imagem

Configuração final


Bem, criamos tudo o que nosso armazenamento precisa, mas ainda falta uma coisa: juntar tudo. Eu vou fazer isso no módulo de aplicativo, mas você pode aplicar o mesmo no módulo principal do seu aplicativo.

Vamos adicionar um módulo de aplicação:

imagem

O que fizemos aqui:

  1. Importamos nossas caixas de velocidades e as fornecemos no módulo de armazenamento forRoot.
  2. Importamos nossos efeitos e os fornecemos dentro da matriz no módulo de efeitos forRoot.
  3. Definimos a configuração do módulo de estado do roteador que fornece o roteador stateKey.
  4. E adicionamos ferramentas de desenvolvedor de loja se o ambiente não for produção.

Os dois primeiros passos são necessários, enquanto os passos 3 e 4 são altamente recomendados, mas não são necessários.

Agora finalmente terminamos ... podemos usar nosso armazenamento em componentes!

Uso de armazenamento em alguns componentes


Estamos chegando ao fim! Vamos ver como usar nosso armazenamento ...

Primeiro, vamos obter a configuração quando o aplicativo iniciar:

imagem

  1. Estamos adicionando armazenamento ao nosso app.component.
  2. Definimos a propriedade component como o valor do seletor na configuração, porque queremos exibir algumas dessas informações em HTML.
  3. No onInit, enviamos a ação para obter a configuração.

Isso é tudo ... Já estamos codificando um efeito que controlará essa ação e um redutor que manipulará esse efeito. Assim que a loja entrar em um novo estado, o seletor alterará o valor de nossa propriedade.

Como associar isso ao HTML:

imagem

Assim que config $ tiver um valor, nós o veremos em HTML.

Agora vamos ver a lista de usuários (containers / users / users.component.ts):

imagem

  1. Assim como gerenciamos a configuração, obteremos uma lista de usuários. Primeiro, injetamos o repositório no componente do usuário.
  2. No onInit, publicamos uma ação para obter usuários.
  3. Criamos uma propriedade para o componente e atribuímos a ele uma lista de usuários usando o seletor de lista de usuários.

O HTML fica assim:

imagem

Exibimos a lista de usuários no componente de apresentação, enviando a lista e associando o usuário selecionado à função de navegação, que pode ser vista no componente de contêiner de usuário acima.

Vejamos o componente do contêiner personalizado:

imagem

este componente recebe o identificador de parâmetro da rota ativada e você provavelmente já conhece o restante, envia o identificador como parâmetro, seleciona o usuário selecionado ...

Se você estiver depurando o aplicativo, poderá ver as ferramentas do desenvolvedor, que são bastante simples para usar ... mas neste artigo, estudamos o suficiente, e espero que você possa descobrir facilmente essas ferramentas.

Conclusão


Neste artigo, tentei fornecer uma introdução clara e compreensível ao NGRX, fornecendo tudo o que você precisa saber para iniciar o desenvolvimento usando esta ferramenta.

Eu realmente espero que o artigo o ajude a entender o modelo de ação e recomende que você faça o download e brinque um pouco com o código.

All Articles