Conforme uma aplicação React cresce, uma pergunta se torna inevitável: onde deve viver o estado que é compartilhado entre múltiplos componentes distantes na árvore? Passar dados via props funciona bem para relações diretas entre pai e filho, mas se torna insustentável quando um dado precisa atravessar cinco ou seis níveis de componentes que não têm relação direta com ele — o problema conhecido como prop drilling. Neste artigo, comparamos as principais soluções de gerenciamento de estado global e como escolher a certa para cada estágio do projeto.
O problema do prop drilling
Imagine um dado de usuário autenticado que precisa estar disponível no cabeçalho, no menu lateral e em um formulário de checkout, todos em partes diferentes da árvore de componentes. Passar essa informação via props exige que cada componente intermediário — mesmo aqueles que não usam o dado diretamente — o receba e repasse adiante. Isso não só polui a assinatura de cada componente, como torna a refatoração arriscada, já que remover um componente intermediário pode quebrar o fluxo de dados de forma não óbvia.
Context API: a solução nativa do React
A Context API resolve o prop drilling permitindo que qualquer componente na árvore acesse um valor diretamente, sem precisar recebê-lo via props. É a solução mais simples para estados que mudam com pouca frequência, como tema visual, idioma ou dados de autenticação. O ponto de atenção é que, por padrão, qualquer mudança no valor do contexto provoca a re-renderização de todos os componentes que o consomem — o que pode se tornar um problema de performance em contextos que mudam com muita frequência ou que carregam objetos grandes.
const UsuarioContext = createContext(null);
function App() {
const [usuario, setUsuario] = useState(null);
return (
<UsuarioContext.Provider value={{ usuario, setUsuario }}>
<Dashboard />
</UsuarioContext.Provider>
);
}
Redux: previsibilidade em troca de mais código
Redux continua sendo a referência para aplicações com fluxos de estado complexos e regras de negócio elaboradas, especialmente quando é necessário rastrear precisamente cada mudança de estado (útil para debugging com ferramentas como Redux DevTools, que permitem "viajar no tempo" entre estados anteriores). A crítica histórica ao Redux é o volume de código boilerplate necessário para ações e reducers, algo que o Redux Toolkit — a forma moderna recomendada de usar Redux — resolveu significativamente, reduzindo a verbosidade sem perder a previsibilidade do padrão original.
Redux não é sobre gerenciar estado — é sobre tornar mudanças de estado rastreáveis e previsíveis, o que tem valor real em aplicações onde bugs de estado são caros de depurar.
Zustand: simplicidade sem sacrificar performance
Zustand ganhou popularidade por oferecer uma API minimalista, sem a necessidade de envolver a aplicação em providers ou escrever reducers extensos, enquanto ainda resolve o problema de re-renderizações desnecessárias — componentes só re-renderizam quando a parte específica do estado que eles consomem muda, não o objeto inteiro. Para times que acham Redux excessivamente verboso para o tamanho do projeto, mas ainda querem uma solução robusta fora da Context API nativa, Zustand costuma ser um meio-termo eficaz.
import { create } from 'zustand';
const useUsuarioStore = create((set) => ({
usuario: null,
login: (dados) => set({ usuario: dados }),
logout: () => set({ usuario: null }),
}));
Estado do servidor não é o mesmo que estado global
Um erro comum é tratar dados vindos de uma API (como uma lista de produtos ou pedidos) da mesma forma que estado puramente local da aplicação (como um tema ou um filtro selecionado). Bibliotecas como React Query (TanStack Query) e SWR foram criadas especificamente para gerenciar estado de servidor — cuidando de cache, revalidação automática, estados de carregamento e erro — e devem ser usadas em conjunto, não em substituição, a uma solução de estado global para dados puramente do cliente.
Como escolher a solução certa
Para aplicações pequenas ou médias, com poucos dados verdadeiramente globais, a Context API combinada com hooks customizados costuma ser suficiente e evita dependências adicionais. Para aplicações com fluxos de estado complexos, múltiplas equipes trabalhando simultaneamente ou necessidade forte de rastreabilidade, Redux Toolkit continua sendo uma escolha sólida. Para times que priorizam simplicidade de código sem abrir mão de performance, Zustand é uma alternativa cada vez mais adotada. Em todos os casos, separar estado de servidor (via React Query ou similar) do estado de cliente evita complexidade desnecessária na camada de estado global.
Considerações finais
Não existe uma solução de estado global universalmente correta — a escolha depende da complexidade real da aplicação e das preferências da equipe quanto a verbosidade versus explicitação. Adotar uma ferramenta robusta demais para um projeto simples adiciona complexidade desnecessária; adotar uma solução simples demais para um projeto complexo gera dívida técnica que aparece mais cedo do que se espera. Se sua equipe está avaliando a arquitetura de estado de uma aplicação React, a equipe da ASL Software Engineering pode ajudar nessa decisão. Fale com a gente.