As melhores ferramentas de gerenciamento de estado do React para aplicativos corporativos
Publicados: 2022-03-11Os desenvolvedores de aplicativos React de nível empresarial sabem como o gerenciamento de estado é crucial para uma experiência coerente do usuário final.
No entanto, o usuário não é o único afetado pelo gerenciamento de estado. Os desenvolvedores do React criam e mantêm o estado. Eles querem que o gerenciamento de estado seja simples, extensível e atômico. O React se moveu nessa direção ao introduzir ganchos.
Podem surgir problemas quando o estado deve ser compartilhado entre muitos componentes. Os engenheiros precisam encontrar ferramentas e bibliotecas que atendam às suas necessidades e, ao mesmo tempo, atender aos altos padrões necessários para aplicativos de nível empresarial.
Neste artigo, analisarei e compararei as bibliotecas mais populares e escolherei a mais adequada para gerenciamento de estado em um aplicativo de nível corporativo.
Recursos integrados de gerenciamento de estado de reação
O React tem uma excelente ferramenta para fornecer dados em vários componentes. O objetivo principal do Contexto é evitar a perfuração de hélices. Nosso objetivo é obter uma ferramenta fácil de usar para gerenciar o estado em vários cenários que podem ser encontrados em aplicativos corporativos: atualizações frequentes, reformulações, introdução de novos recursos e assim por diante.
Embora tudo isso seja teoricamente factível com o Context, exigiria uma solução personalizada que requer tempo para configurar, oferecer suporte e otimizar. A única vantagem do Context é que ele não depende de uma biblioteca de terceiros, mas isso não pode compensar o esforço para manter essa abordagem.
Além disso, Sebastian Markbage, membro da equipe do React, mencionou que a nova Context API não foi construída e otimizada para atualizações de alta frequência, mas sim para atualizações de baixa frequência, como atualizações de temas e gerenciamento de autenticação.
Examinando bibliotecas existentes
Existem dezenas de ferramentas de gerenciamento de estado no GitHub (por exemplo, Redux, MobX, Akita, Recoil e Zustand). No entanto, levar cada um deles em consideração levaria a infinitas pesquisas e comparações. É por isso que reduzi minha seleção aos três principais concorrentes com base em sua popularidade , uso e mantenedor .
Para tornar a comparação explícita, usarei os seguintes atributos de qualidade:
- Usabilidade
- Manutenibilidade
- atuação
- Testabilidade
- Escalabilidade (funciona com o mesmo desempenho nos estados maiores)
- Modificabilidade
- Reutilização
- Ecossistema (tem uma variedade de ferramentas auxiliares para estender a funcionalidade)
- Comunidade (tem muitos usuários e suas perguntas são respondidas na web)
- Portabilidade (pode ser usado com bibliotecas/frameworks diferentes do React)
Restaurado
Redux é um contêiner de estado criado em 2015. Tornou-se muito popular porque:
- Não havia alternativa séria quando foi lançado.
- Ele forneceu a separação entre o estado e as ações.
- A mágica
react-reduxpermitiu a conexão de estado direta. - O co-criador da biblioteca é o aclamado desenvolvedor do Facebook e membro da equipe principal do React, Dan Abramov.
Você tem uma loja global onde seus dados residem. Sempre que precisar atualizar a loja, você despacha uma ação que vai para o redutor . Dependendo do tipo de ação, o redutor atualiza o estado de forma imutável.
Para usar Redux com React, você precisará inscrever os componentes nas atualizações da loja via react-redux .
Exemplo de API Redux
As partes fundamentais do Redux na base de código que o diferenciam das outras ferramentas são os slices. Eles contêm toda a lógica de ações e redutores.
CodeSandbox
// slices/counter.js import { createSlice } from "@reduxjs/toolkit"; export const slice = createSlice({ name: "counter", initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); export const actions = slice.actions; export const reducer = slice.reducer; // store.js import { configureStore } from "@reduxjs/toolkit"; import { reducer as counterReducer } from "./slices/counter"; export default configureStore({ reducer: { counter: counterReducer } }); // index.js import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import App from './App' import store from './store' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // App.js import React from "react"; import { useSelector, useDispatch } from "react-redux"; import { actions } from "./slices/counter"; const App = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <div> <button onClick={() => dispatch(actions.increment())}>Increment</button> <span>{count}</span> <button onClick={() => dispatch(actions.decrement())}>Decrement</button> </div> </div> ); }; export default App;Atributos de qualidade
- Usabilidade . O Redux ficou muito simples com a introdução do pacote oficial do kit de ferramentas. Você cria uma fatia (uma combinação do estado inicial, redutores e ações), passa-a para o armazenamento e acessa-a em um componente por meio de ganchos.
- Manutenibilidade . Redux é simples. Não requer conhecimento profundo para entender como melhorar ou reparar algo.
- Desempenho . O principal influenciador de desempenho com Redux é o engenheiro de software. Redux é uma ferramenta direta sem muita lógica. Se você perceber que as atualizações de estado estão lentas, siga as diretrizes oficiais para torná-las mais rápidas.
- Testabilidade . O Redux consiste em funções puras (ações e redutores), tornando-o ótimo para testes de unidade. Ele também fornece o mecanismo para escrever testes de integração onde o armazenamento, as ações e os redutores trabalham juntos.
- Escalabilidade . Por padrão, o Redux tem um estado global, dificultando o dimensionamento. No entanto, existe uma biblioteca redux-dynamic-modules que permite a criação de redutores modulares e middleware.
- Modificabilidade . Personalizar o Redux é uma tarefa fácil porque suporta middleware.
- Reutilização . O Redux é agnóstico de framework, por isso é muito bom em reutilização.
- Ecossistema . O Redux oferece um ecossistema gigante de complementos, bibliotecas e ferramentas úteis.
- Comunidade . Redux, a biblioteca de gerenciamento de estado mais antiga em nossa comparação, acumulou uma grande comunidade com uma base de conhecimento significativa. Existem ~30.000 (~19.000 respondidas) perguntas com uma tag
reduxno Stack Overflow. - Pulso . O Redux é atualizado e mantido regularmente.
MobX
MobX é outra biblioteca relativamente antiga com 23.000 estrelas no GitHub. O que o diferencia do Redux é que ele segue o paradigma OOP e usa observáveis. O MobX foi criado por Michel Weststrate e atualmente é mantido por um grupo de entusiastas de código aberto com a ajuda de Mendix, com sede em Boston.
No MobX, você cria uma classe JavaScript com uma chamada makeObservable dentro do construtor que é seu armazenamento observável (você pode usar o decorador @observable se tiver o carregador apropriado). Em seguida, você declara propriedades (estado) e métodos ( ações e valores calculados ) da classe. Os componentes assinam esse armazenamento observável para acessar o estado, valores calculados e ações.
Outra característica essencial do MobX é a mutabilidade. Permite atualizar o estado silenciosamente caso você queira evitar efeitos colaterais.
Exemplo de API MobX
Um recurso exclusivo do MobX é que você cria classes ES6 quase puras com toda a magia escondida sob o capô. Requer menos código específico da biblioteca para manter a concentração na lógica.
CodeSandbox
// stores/counter.js import { makeAutoObservable } from "mobx"; class CounterStore { value = 0; constructor() { makeAutoObservable(this); } increment() { this.value += 1; } decrement() { this.value -= 1; } } export default CounterStore; // index.js import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "mobx-react"; import App from "./App"; import CounterStore from "./stores/counter"; ReactDOM.render( <Provider counter={new CounterStore()}> <App /> </Provider>, document.getElementById("root") ); // App.js import React from "react"; import { inject, observer } from "mobx-react"; const App = inject((stores) => ({ counter: stores.counter }))( observer(({ counter }) => { return ( <div> <div> <button onClick={() => counter.increment()}>Increment</button> <span>{counter.value}</span> <button onClick={() => counter.decrement()}>Decrement</button> </div> </div> ); }) ); export default App;Atributos de qualidade
- Usabilidade . Um armazenamento observável é o único ponto de entrada para gerenciamento de estado. Ele torna o uso do MobX simples porque você tem o único lugar para modificar.
- Manutenibilidade . É uma desvantagem considerável. Sem conhecimento da API RxJS, você não conseguirá alcançar o resultado desejado. Usar o MobX em uma equipe mal qualificada pode levar a problemas de inconsistência de estado.
- Desempenho . MobX consiste em lojas independentes e permite que você assine as únicas que você precisa. É muito eficaz.
- Testabilidade . Lojas observáveis são objetos JavaScript simples com funcionalidade reativa escondida dentro. O teste é o mesmo que para qualquer outra classe JavaScript.
- Escalabilidade . Os armazenamentos observáveis são divididos logicamente; não há dificuldade em dimensionar o MobX.
- Modificabilidade . MobX permite criar observáveis personalizados com comportamentos modificados. Além disso, existe um conceito chamado reações. Reações modelam efeitos colaterais automáticos. Essas coisas tornam o MobX muito personalizável.
- Reutilização . MobX é agnóstico de frameworks, por isso é muito bom em reutilização.
- Ecossistema . Existem centenas de extensões disponíveis para MobX.
- Comunidade . MobX tem muitos fãs dedicados. Existem ~ 1.600 (~ 1.000 respondidas) perguntas com a tag
mobxno Stack Overflow. - Pulso . MobX é atualizado e mantido regularmente.
Recuo
Recoil é um recém-chegado relativo, a mais recente criação da equipe React. A ideia básica por trás disso é uma implementação simples de recursos React ausentes, como estado compartilhado e dados derivados.

Você pode estar se perguntando por que uma biblioteca experimental é revisada para projetos de nível empresarial. Em primeiro lugar, o Recoil é um dos tópicos mais discutidos na comunidade React no momento. Em segundo lugar, o Recoil é apoiado pelo Facebook e já é usado em alguns de seus aplicativos, o que significa que se tornará uma versão estável em algum momento. Por fim, é uma abordagem totalmente nova para compartilhar o estado no React, e tenho certeza que mesmo que o Recoil esteja obsoleto, haverá outra ferramenta que seguirá o mesmo caminho.
Recoil é construído em cima de dois termos: atom e selector . Um átomo é uma peça de estado compartilhado. Um componente pode se inscrever em um átomo para obter/definir seu valor.
Como você pode ver na imagem, apenas os componentes inscritos são renderizados novamente quando o valor é alterado. Isso torna o Recoil muito eficiente.
Outra grande coisa que o Recoil tem fora da caixa é o seletor . O seletor é um valor agregado de um átomo ou outro seletor. Para os consumidores, não há diferença entre átomo e seletor, eles só precisam se inscrever em alguma parte reativa e usá-la.
Sempre que um átomo/seletor é alterado, os seletores que o utilizam (ou seja, estão inscritos nele) são reavaliados.
Exemplo de API de recuo
O código do Recoil é muito mais diferente do que seus concorrentes. Ele é baseado em ganchos do React e se concentra mais na estrutura do estado do que na mutação desse estado.
CodeSandbox
// atoms/counter.js import { atom } from "recoil"; const counterAtom = atom({ key: "counter", default: 0 }); export default counterAtom; // index.js import React from "react"; import ReactDOM from "react-dom"; import { RecoilRoot } from "recoil"; import App from "./App"; ReactDOM.render( <RecoilRoot> <App /> </RecoilRoot>, document.getElementById("root") ); // App.js import React from "react"; import { useRecoilState } from "recoil"; import counterAtom from "./atoms/counter"; const App = () => { const [count, setCount] = useRecoilState(counterAtom); return ( <div> <div> <button onClick={() => setCount(count + 1)}>Increment</button> <span>{count}</span> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> </div> ); }; export default App;Atributos de qualidade
- Usabilidade . Recoil é uma das ferramentas mais fáceis de usar porque funciona como
useStateno React. - Manutenibilidade . Tudo o que você precisa fazer no Recoil é manter seletores e ganchos dentro dos componentes – mais valor, menos clichê.
- Desempenho . O Recoil constrói uma árvore de estado fora do React. A árvore de estado permite que você obtenha e ouça as coisas que você precisa, não as mudanças da árvore inteira. Também é bem otimizado sob o capô.
- Testabilidade . Recoil fornece um mecanismo para testar seus átomos e seletores.
- Escalabilidade . Um estado que se divide em várias partes independentes o torna um bom jogador em escalabilidade.
- Modificabilidade . O Recoil é responsável apenas por armazenar valores e suas agregações. Ele não tem fluxo de dados para que possa ser personalizado facilmente.
- Reutilização . O Recoil depende do React. Não pode ser reutilizado em outro lugar.
- Ecossistema . Não há ecossistema para Recoil no momento.
- Comunidade . Recoil é muito novo para ter uma grande comunidade. Existem cerca de 70 perguntas com a tag
recoiljsno Stack Overflow. - Pulso . O Recoil é atualizado com pouca frequência (seis meses se passaram entre suas duas atualizações mais recentes). Ele também tem muitos problemas em aberto no GitHub.
Escolhendo a ferramenta correta de gerenciamento de estado de reação
Como essas bibliotecas de gerenciamento de estado global do React se comparam quando se trata de aplicativos de nível empresarial?
O Recoil é jovem e fresco, mas não tem comunidade nem ecossistema no momento. Embora o Facebook esteja trabalhando nisso e a API pareça promissora, um enorme aplicativo React não pode contar com uma biblioteca com suporte fraco da comunidade. Além disso, é experimental, tornando-o ainda mais inseguro. Definitivamente, não é uma boa opção para aplicativos corporativos React hoje, mas vale a pena ficar de olho nele.
MobX e Redux não compartilham nenhum desses problemas e a maioria dos grandes players do mercado os usa. O que os diferencia um do outro é a curva de aprendizado. MobX requer uma compreensão básica de programação reativa. Se os engenheiros envolvidos no projeto não forem qualificados o suficiente, o aplicativo pode acabar com inconsistências de código, problemas de desempenho e maior tempo de desenvolvimento. O MobX é aceitável e atenderá às suas necessidades se sua equipe estiver ciente da reatividade.
O Redux também tem alguns problemas, principalmente em relação à escalabilidade e desempenho. No entanto, ao contrário do MobX, existem soluções comprovadas para esses problemas.
Levando em consideração todas as vantagens e desvantagens, e considerando minha experiência pessoal, recomendo o Redux como a melhor opção para aplicativos de nível corporativo React.
