Gabriel / Ramos

⟨ pintor de pixel ⟩

  • Blog
  • Context, Redux e gerenciamento de estado

Context, Redux e gerenciamento de estado

Algumas ideias, opiniões e pensamentos sobre o tema

5 min. de leitura

Foto por Maarten van den Heuvel

Quando o assunto é aplicações front-end (mais especificamente utilizando React), é bem comum que sejam discutidas algumas soluções de gerenciamento de estado com o objetivo de desatrelar esse gerenciamento de um componente específico.

Os ganhos geralmente são claros e quando sua aplicação vai crescendo eles se tornam ainda mais visíveis, alguns deles são:

  • Isolamento de responsabilidades: seus componentes ficarão única e exclusivamente responsáveis por lidar com um dado X ou Y, independente da forma como ele é consultado;
  • Desacoplamento de estado: afinal, você tende a remover esses estados de componentes "pais" ou "containers" e a realizar alguma abstração para que esse estado seja compartilhado de outra forma;
  • Estado previsível: desacoplando esse estado, muito provavelmente existirá uma estrutura que ficará responsável por receber novas entradas de ações e modificar esse estado global para propagar aos componentes relacionados;
  • Aplicação de pub/sub, observer e nomes derivados: como comentado no fim do ponto anterior, de quebra, você muito provavelmente vai estar utilizando alguma estrutura em que "subscreve" seus componentes a uma alteração de um "emissor" de mudanças de estado;
  • Evitar o famoso "prop drilling": o cenário onde seu componente possui um estado e passa para um componente filho como prop, que passa para outro componente filho, e assim por diante até que sua árvore acabe e pode induzir alguns problemas em sua aplicação.

No entanto, existem algumas formas de aplicar esses gerenciamentos de estado e acho que podemos comentar algumas delas por aqui.

A mais primordial: com um componente "container" ou "pai"

A mais clássica e geralmente a que é utilizada no início dos projetos, antes que eles cresçam e precisem de outras soluções rebuscadas. Nesse cenário você desenvolve um componente responsável por manter uma lógica principal com o estado da sua aplicação e esse componente em específico acaba crescendo ao longo do tempo.

Embora ainda fique (geralmente) restrita a um componente que "sabe demais" sobre a sua aplicação, com certeza é uma sementinha que faz com que você enxergue o benefício das próximas abordagens.

Geralmente essa opção acaba sendo deixada de lado quando as telas do seu projeto crescem e seu componente acaba tendo que lidar com estados da sua aplicação que não são relacionados. Claro, você poderia manter esse padrão e criar um outro componente responsável por outros pedaços de estado. Entretanto, nesse cenário as desvantagens dessa opção acabam ficando claras justamente por esse trabalho manual que você vai começar a duplicar suas lógicas de estado em algumas "cascas" bem parecidas.

Uma solução pré-pronta: utilizando Context (e, talvez, useReducer)

Você já deve ter ouvido o termo Context API (disponível até em uma implementação com Hooks) e pode ser uma solução viável a médio prazo.

Utilizando Context API você consegue trabalhar com os cenários onde você possui um componente "provedor" (ou provider) e qualquer componente abaixo na sua árvore de renderização consegue atuar como "consumidor" (ou consumer), consultando e utilizando essas informações.

É uma boa solução e atende bem às necessidades de algumas aplicações. Com a utilização do hook useReducer acaba ficando ainda mais versátil e permite utilizar implementações com actions/dispatchers/reducers (chegando perto da próxima alternativa que veremos).

Redux e seu histórico nas aplicações de larga escala

Redux é outro personagem já bastante conhecido por ajudar nessa questão de gerenciamento de estado, e implementa uma arquitetura que é bem próxima ao que o hook useReducer implementa.

Geralmente é uma solução mais viável a longo prazo, justamente por ser adotado por boa parte da comunidade e estar no mercado há um bom tempo, então todo suporte em questões técnicas, documentação e idealização (como posts e artigos na internet) já seguem o Redux como uma alternativa consolidada.

Context vs Redux: O embate

Olhando os dois cenários, é facil de pensar algo como:

"Por que utilizar Redux, se posso manter meu gerenciamento de estado mais simples, com soluções que já são fornecidas pelo próprio React?"

Esse tipo de raciocínio realmente deve ser considerado. Porém, você deve colocar na balança outros pontos ao optar por uma dessas opções:

  • O intuito com a sua aplicação: particularmente, gosto de utilizar Context API para algumas provas de conceito (ou POCs) que acabam sendo projetos momentâneos e serão reescritos de uma maneira mais adequada caso se provem válidos. Às vezes acabo utilizando como uma camada "extra" que fica responsável por fazer chamadas em algumas APIs e prover funções que realizam esses acessos e disponibilizam os dados de retorno, geralmente nos casos que não utilizo como uma ferramenta exclusivamente para centralizar estado;
  • O tamanho da sua aplicação: realmente, se sua aplicação é um projeto pessoal que só você usa, uma prova de conceito ou um trabalho que vai ser deixado de lado em breve, talvez utilizar Redux só te faça instalar alguns pacotes extras sem necessidade (lembrando que Redux não necessariamente está atrelado a pacotes específicos e está mais relacionado ao conceito e aos "personagens" envolvidos no gerenciamento de estado proposto pela arquitetura).
  • Utilizar Context API te trará alguns trabalhos manuais extras: uma ferramenta como o Redux, mais consolidada no mercado e mantida por um time tão extenso (e com nomes de peso na comunidade) já traz algumas garantias de performance e qualidade que você, muito provavelmente, terá que garantir por conta própria (não que seja impossível, mas você apenas teria que se preocupar com algumas dores que já foram dores de outros usuários e desenvolvedores);
  • Redux é amplamente difundido na comunidade: plugins (como o Redux DevTools), ferramentas (como tracking de erro utilizando Sentry) e várias outras funcionalidades possuem integrações já "a pronta entrega";
  • Vale a pena reinventar a roda (e, provavelmente, manter ela do jeito que ela já é)?

Se você ainda não tem uma opinião formada, vale lembrar que, no fim, o pacote react-redux (que contém os bindings de Redux para sua aplicação em React) também utiliza a Context API em sua implementação e você pode confirmar isso no próprio Github. Talvez isso traga alguma tranquilidade se estiver preocupado como eles lidam internamente com esses provedores.


Compartilhe