Article image
Samuel Costa
Samuel Costa17/04/2021 13:28
Compartilhe

Entendendo NgRx - Avanade Angular Projeto API - Weather

  • #Angular
  • #Redux
  • #TypeScript

Programar com Angular tem sido muito proveitoso e prático, mas também um grande desafio. Conceitos como o de módulos, Observables e outros dão um verdadeiro nó na cabeça. E quando comecei a desenvolver o projeto da api-weather, ministrada pelo instrutor João Victor Ghignatti, percebi o poder que este framework traz, mas também o nível de conhecimento e prática que ele exige.

O que quero compartilhar com vocês hoje é sobre o que aprendi sobre o ngrx e como gerenciamento de estado pode ajudar ao criarmos aplicações escaláveis. Antes, quero ressaltar que ainda estou digerindo os conceitos (literalmente precisei construir o app 4 vezes para entender), e se você, caro leitor perceber algo de errado, sinta-se a vontade para comentar. Vamos lá!

Projeto: Site em Angular para consulta da previsão do tempo via API (openweather)

Nesse projeto fomos introduzidos ao NgRx, o redux do angular. O conceito é simples:

Digamos que na sua aplicação angular, você tenha 2 componentes, A e B respectivamente. E esses 2 componentes utilizem a mesma informação, que chamaremos de "I" (grande criatividade Samuel).

Em um momento, B decide fazer alterações em I, tornando ele um "IL". Assim, B alterou o estado, a forma da informação inicial, mas para A, I continuou a mesma coisa. "A" não sabe das mudanças de I e assim, sua visão da informação fica atrasada.

Aqui temos apenas 2 componentes, mas no mundo real uma aplicação pode ter literalmente dezenas de componentes que escutam e alteram informações. Assim, é necessário um sistema de gerenciamento de estado que em termos simples seria algo como: "Se B altera o componente "I" para "IL", quando A for visualizar a informação, ele encontrará "IL", e não "I".

Assim chegamos no Ngrx. Segundo a definição no próprio site, é um framework para construção de aplicações reativas em Angular. No nosso exemplo citado, o componente B "avisa" que deseja mudar a informação "I" e passa o novo valor "IL". A informação está guardada na Store, uma caixa grandona que guarda as informações. A Store recebe o aviso de B, junto com as novas informações e faz o processo para modificar a informação para "IL". Agora, para pegar a nova informação, B precisa pedir, ou "selecionar" a informação nova. Dessa forma, mesmo que não seja "B" que altere a informação, ele sempre será atualizado com a informação mais recente.

Passando pro código, temos as Actions, Reducers e Selectors e Effects, que são apresentados no projeto. O professor cita, que uma boa prática é sempre comecar pelas actions. No nosso projeto fictício, o componente B possui um input que registra a nova informação vinda do usuário, que deverá alterar a que está registrada na Store; e o componente A é responsável por mostrar na tela essa informação. Note que os 2 componentes interagem com a mesma informação. Assim é importante ter um gerenciamento de estado na aplicação. No nosso componente B temos algo como:

informacaoComponenteB.component).ts
alterarInformacao(){
  const informacao = "Texto Novo";
  this.store.dispatch(acoesDoComponenteB.enviarNovaInformacao({ informacao }));
}

O comando this.store.dispatch (store:Store é importada no construtor) é o responsável por passar o "aviso" da nova informação. Veja que o método recebe um parâmetro que é a nossa nova informação.

A nossa action seria definida da seguinte forma:

informacao.actions.ts
export const enviarNovaInformacao = createAction(
  ' [Componente B] Enviar Nova Informação ',
  props <{ informacao:string }>() 
)

A primeira parte do método é um rótulo informativo onde você vê quem dispara a action e o que ela tem q fazer (deixarei o link da extensão de desenvolvimento para visualização do estado no fim). A segunda parte é responsável por definir o que essa action precisa para funcionar, no caso uma informação do tipo string.

Quando ela é disparada, nossos reducers são avisados e tratarão de atualizar a informação com base nas regras definidas:

informacao.reducers
import * as todasAsActions from 'componentB.actions.ts';

export interface EstadoDaInformacao{
informacao:string;
}

export const estadoInicialDaInformacao: EstadoDaInformacao ={
informacao:' ';
}

const reducer = createReducer(
  estadoInicialDaInformacao, 
  on(todasAsActions.enviarNovaInformacao, (state, { informacao }) =>({
  ...state,
  informacao,
})),
);

export function homeReducer (state:EstadoDaInformacao|undefined, action:Action):EstadoDaInformacao{
return reducer(state, action)
}

Eu sei, a primeira vez que vi isso eu literalmente travei, e precisei ver mais 4 vezes pra comecar a entender (sério, não desista!), mas vamos lá:

Primeiro, defina o estado inicial da sua informação, o que ela precisa para ser definida, no nosso caso, uma informação do tipo string;

Defina o estado inicial da sua informacao, a cara que ela vai ter logo no inicio, pode ser um texto vazio como no nosso exemplo;

Crie o reducer: ele precisa de um estado inicial (que voce acabou de definir) e da acao que ele irá reagir (programacao reativa rules). Perceba que nesse momento ele pega aquela primeira informacao que voce passou la no componente, sacou? Com um estado e essa informacao, ele retorna um novo estado e vualá, a informacao foi alterada para todos que querem ver.

No final, crie uma funcao funcional que irá abstrair o comportamento e irá funcionar todas as vezes.

Já peço perdão pelo longo artigo, mas se ficou até aqui, você pode estar com algumas dúvidas:

  • Como o componente A pega a nova informação?
  • Posso receber informação de outros locais sem ser do usuário, como uma api ou backend?
  • Como faço o setup inicial?

Irei criar a parte 2 desse artigo e espero publicá-la em breve, pois faltaram diversos outros conceitos como estrutura de diretórios, nomenclaturas e etc. E já peço 2 coisas:

Deixem sugestões de configurações, dicas, melhorias e por favor, se virem algum erro sintam-se à vontade para apontá-los;

E comente o que achou deste artigo, se ele te ajudou ou não, espero que sim kkkk.

Ah, e sobre a imagem no início do artigo: Como eu disse, tive dificuldades para realizar o projeto. Então decidi criá-lo do zero, apenas com html simples para entender data-bindings, comunicacao dos componentes e outras coisas. A prática leva a perfeição!

E entendo como pode ser difícil entender todos estes conceitos no início, mas novamente, não desista DEV!

Comente aqui se deseja um artigo explicando a configuração Inicial do NgRx!

Links:

Redux DevTools para chrome:

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=pt-BR

Site do NgRx:

https://ngrx.io/

Meu linkedin (me chama lá):

www.linkedin.com/in/samuel-ferreira-da-costa-025b72199

Compartilhe
Comentários (2)
Samuel Costa
Samuel Costa - 28/04/2021 13:42

Obrigado Lucas!!!

Lucas Magalhães
Lucas Magalhães - 17/04/2021 14:19

Se puxando Samuel! Parabéns.