Nos últimos meses, tenho usado ferramentas de IA para acelerar a escrita de componentes em React. O ganho de produtividade é real, mas um efeito colateral vem me tirando o sono: uma avalanche de Context Providers espalhados pela árvore de componentes, gerando um “Hadouken” de props e wrappers no layout.
O problema
- Múltiplos Contexts: Cada feature criada pela IA ganhou seu próprio contexto e as chamadas de providers ficaram bonitas assim:
- Layout poluído: Os componentes filhos acabam recebendo excesso de re-renders e chamadas de selectors, tornando o layout lento e difícil de debugar.
- Acoplamento alto: Qualquer nova feature IA-gerada exige criar mais Contexts ou modificar providers já existentes, ampliando ainda mais o “Hadouken”.
Por que a IA escolheu Context?
A IA tende a seguir padrões genéricos e bem documentados. Como o Context do React é frequentemente usado para compartilhar estado entre componentes, ele vira o “go-to” da IA sempre que surge uma necessidade de estado global. Mesmo quando um estado local ou um simples hook resolveria melhor, a IA costuma supercompartimentalizar, criando um Provider para cada pequena responsabilidade. Além disso:
- A documentação oficial e os tutoriais são cheios de exemplos com Contexts
- A IA não conhece a frequência de uso ou o escopo real do dado
- Criar múltiplos Providers parece modular, mas gera um acoplamento oculto e dificulta o refactor
Como identificar o que realmente precisa de contexto
Nem todo estado merece um contexto global. Um bom critério é observar quantos lugares diferentes acessam e reagem àquele dado, e com que frequência ele muda.
Um ótimo exemplo de exagero comum é o uso de Context
para notificações (toasts). Elas são exibidas em um único lugar da tela, ativadas por eventos, e não precisam ser lidas por múltiplos componentes. Criar um NotificationContext
global só aumenta o acoplamento — nesse caso, um useNotification()
com estado local ou pub/sub interno resolve bem melhor, sem precisar de Provider.
Já para estados realmente globais, como autenticação (UserAuth
), que são acessados por diversos pontos da aplicação e mudam pouco, o Context
continua sendo uma boa escolha.
-
UserAuth (Autenticação): acessado por toda a aplicação — navbar, páginas privadas, carregamento de dados do usuário. Esse sim justifica o uso de
Context
, pois é global, muda pouco e evita prop drilling. -
Notificações (Toasts): normalmente são exibidas em um único lugar na tela. Elas são eventos, não estado compartilhado. Nesse caso, um
useNotification()
com state interno ou pub/sub resolve melhor — sem precisar de Provider.
Estratégia de refatoração
Hooks customizados
Substituí o acesso direto aos contextos por hooks específicos ( useNotify()
), que internamente usam useContext
. Isso me deu várias vantagens:
- Redução de boilerplate
- Centralização da lógica de erro (“Provider não encontrado”)
- Facilidade para mockar em testes
Ao encapsular o acesso em hooks, consegui simplificar os componentes e limitar o impacto do contexto ao que realmente precisa dele.
Quando usar Context vs. quando usar Hook customizado
Situação | Use Context diretamente | Use Hook customizado |
---|---|---|
Compartilhamento global de estado simples | ✅ Sim | ➖ Opcional |
Estados com lógica de acesso e fallback | 🔶 Evite | ✅ Sim |
Testes de unidade e mocks | 🔶 Mais difícil | ✅ Mais fácil |
Reuso de lógica em múltiplos componentes | 🔶 Verboso | ✅ Simples e direto |
Evitar re-renders desnecessários com selectors | 🔶 Complexo | ✅ Encapsulado no hook |
Benefícios alcançados
- Árvore de componentes mais limpa: sem excesso de nesting
- Menos re-renders: graças aos hooks com lógica encapsulada
- Escalabilidade: novos acessos são resolvidos com simples hooks reutilizáveis
Dicas finais para uma refatoração sem dor
- Planeje a migração em fases. Não tente trocar tudo de uma vez.
- Documente os hooks e exemplos de uso. Facilita a adoção pelo time.
- Aproveite para revisar regras de negócio. Hooks compostos são ótimos para encapsular lógica específica.
Top comments (0)