Oi pessoal, tudo bem?
Hoje quero compartilhar um pouco da minha experiência sobre quando é o momento ideal de usar uma biblioteca de gerenciamento de estado em aplicações React.
Comecei a construir um backoffice usando Next.js 14 e, no início, não senti necessidade de implementar nenhuma biblioteca de gerenciamento de estado. Para algumas informações globais, utilizei o React Context, que resolveu bem problemas simples.
Porém, conforme a aplicação cresceu, surgiu a necessidade de compartilhar informações entre componentes mais distantes. Foi aí que me deparei com o famoso problema do prop drilling. Esse cenário começou a tornar o código menos organizado e difícil de manter.
A partir dessa experiência, percebi que estava na hora de considerar o uso de uma solução mais robusta, como Zustand, Redux ou Jotai.
O que é Prop Drilling e por que pode ser um problema?
O prop drilling ocorre quando precisamos passar propriedades de um componente para outro que está distante na hierarquia, atravessando vários níveis intermediários. Em outras palavras, mesmo que um componente intermediário não utilize a propriedade, ele ainda precisa recebê-la e repassá-la para o próximo componente.
Para ilustrar, imagine que temos uma estrutura de componentes como esta:
App
├── Header
│ └── UserMenu
└── Main
└── Sidebar
└── UserProfile
Se quisermos passar informações de um usuário, como o nome, do componente App para o UserProfile, precisaríamos repassar a propriedade manualmente por todos os componentes intermediários:
function App() {
const user = { name: "Gabriel" };
return (
<div>
<Header user={user} />
<Main user={user} />
</div>
);
}
function Header({ user }) {
return <UserMenu user={user} />;
}
function Main({ user }) {
return <Sidebar user={user} />;
}
function Sidebar({ user }) {
return <UserProfile user={user} />;
}
function UserProfile({ user }) {
return <p>Olá, {user.name}!</p>;
}
Este exemplo simples parece inofensivo, mas à medida que a aplicação cresce e mais componentes precisam dessas informações, o código pode rapidamente se tornar confuso e difícil de gerenciar. Qualquer alteração na estrutura da hierarquia pode exigir grandes mudanças no código, aumentando a probabilidade de erros.
Minha Experiência com Prop Drilling
Enquanto trabalhava no desenvolvimento de um backoffice construído com Next.js, comecei enfrentando o problema clássico do prop drilling. No início, a aplicação era relativamente simples, e as informações globais eram gerenciadas eficientemente com o React Context ou passando props entre os componentes.
No entanto, conforme a aplicação cresceu e se tornou mais complexa, alguns componentes precisavam compartilhar informações críticas com outros componentes que estavam distantes na hierarquia. Por exemplo, um componente que exibia uma lista precisava passar dados e funções para outro componente, que, por sua vez, deveria comunicar esses dados a subcomponentes ainda mais específicos. Isso exigiu que muitas propriedades fossem repassadas manualmente por vários níveis de componentes intermediários, mesmo que esses componentes não utilizassem as propriedades diretamente.
Essa abordagem funcionava inicialmente, mas, com o tempo, tornou o código difícil de manter, aumentar ou refatorar. Cada alteração nos componentes superiores tinha um impacto em cascata, exigindo ajustes em diversos pontos do código. Além disso, entender o fluxo dos dados ficou cada vez mais complicado para novos membros da equipe.
Foi nesse momento que percebi a necessidade de uma solução mais robusta para gerenciamento de estado. Bibliotecas como Redux, Zustand e Jotai começaram a fazer muito mais sentido, pois poderiam eliminar o excesso de dependências entre os componentes e centralizar o estado de forma mais clara e eficiente.
Por que escolhi o Zustand?
Com tantas opções disponíveis para gerenciamento de estado, como Redux, MobX, Jotai, e até mesmo o próprio React Context, decidi optar pelo Zustand. Minha escolha foi baseada em alguns fatores importantes:
Simplicidade: O Zustand é extremamente simples de usar. Ele possui uma API enxuta e fácil de entender, o que torna a curva de aprendizado muito menor quando comparado a outras soluções mais robustas, como o Redux.
Leveza: É uma biblioteca leve e sem dependências adicionais, o que contribui para um bundle size menor, mantendo a aplicação performática.
Escalabilidade: Embora minha aplicação ainda seja de porte médio, escolhi o Zustand pensando no futuro. Ele me oferece a flexibilidade para escalar e organizar o estado de forma modular, sem adicionar complexidade desnecessária.
Menos Boilerplate: Diferente de outras bibliotecas, o Zustand não exige a criação de actions ou reducers. Com apenas alguns hooks e configurações simples, já consigo gerenciar o estado global da aplicação de maneira eficiente.
Alternativa ao Context: O React Context é uma excelente solução para casos simples, mas pode se tornar problemático em aplicações maiores devido ao problema de re-renders desnecessários. O Zustand lida melhor com esses cenários, atualizando apenas os componentes que realmente dependem do estado alterado.
A partir do momento em que implementei o Zustand, percebi uma grande melhoria na organização e manutenção do meu código. A lógica de estado ficou centralizada e acessível, sem impactar negativamente a performance ou aumentar a complexidade da aplicação.
Usando Zustand para Resolver o Prop Drilling
Com Zustand, podemos centralizar o estado e acessá-lo diretamente nos componentes que precisam das informações. Aqui está como o exemplo ficaria:
Criando o Store com Zustand
import create from 'zustand';
// Criamos um store centralizado para gerenciar o estado do usuário
const useUserStore = create((set) => ({
user: { name: "Gabriel" }, // Estado inicial
setUser: (newUser) => set({ user: newUser }), // Método para atualizar o estado
}));
Refatorando os Componentes
Agora, em vez de passar o estado como prop por toda a hierarquia, podemos acessar o estado diretamente no componente que precisa dele.
function App() {
return (
<div>
<Header />
<Main />
</div>
);
}
function Header() {
return <UserMenu />;
}
function Main() {
return <Sidebar />;
}
function Sidebar() {
return <UserProfile />;
}
function UserProfile() {
const user = useUserStore((state) => state.user); // Acessamos o estado diretamente
return <p>Olá, {user.name}!</p>;
}
Como Isso Resolve o Prop Drilling?
Estado Centralizado: O estado do usuário está centralizado no store do Zustand.
Acesso Direto: Cada componente que precisa do estado pode acessá-lo diretamente, sem depender de componentes intermediários.
Escalabilidade: Se o estado ou lógica de atualização crescer, podemos gerenciá-lo no store de maneira modular.
Claro! Aqui está uma sugestão para a conclusão do seu artigo:
Conclusão
Escolher o momento certo para introduzir uma biblioteca de gerenciamento de estado em uma aplicação React é uma decisão que depende muito do contexto e das necessidades do projeto. No meu caso, começar com soluções simples, como o React Context, funcionou bem em um primeiro momento. Contudo, à medida que a aplicação cresceu e os problemas de prop drilling começaram a aparecer, optei por adotar o Zustand pela sua simplicidade, leveza e escalabilidade.
Cada projeto tem seus próprios desafios, e não existe uma solução única que atenda a todos os casos. Por isso, é importante avaliar cuidadosamente os problemas que você está enfrentando e escolher a ferramenta que melhor se adapta ao cenário atual e ao crescimento futuro da aplicação.
Se você está começando ou lidando com um projeto de porte pequeno, pode ser que o React Context seja suficiente. Mas, se a sua aplicação começa a demandar um gerenciamento de estado mais robusto, bibliotecas como Zustand, Redux, ou Jotai podem ser uma excelente escolha.
E você? Já enfrentou problemas com prop drilling ou precisou adotar uma solução de gerenciamento de estado? Compartilhe sua experiência nos comentários, adoraria saber como você lidou com isso!
Top comments (0)