Domine React Hooks
Uso disciplinado de Hooks em 2024: efeitos como sincronização, concorrência segura, eliminação de estado derivado, custom hooks como API de domínio e controle real de re-render.
Leonardo David
14 min de leitura
Hooks são poderosos porque tornam composição, estado e efeitos parte do mesmo modelo mental. Eles também são fonte de bugs sutis quando useEffect vira fluxo de controle em vez de sincronização com sistemas externos.
Desde o React 18, com renderização concorrente e Strict Mode executando efeitos duas vezes em desenvolvimento, o uso descuidado de Hooks expõe problemas arquiteturais. O objetivo não é 'fazer funcionar', mas garantir previsibilidade sob concorrência, re-render e transições.
1) Rules of Hooks são invariantes estruturais
Hooks não são funções comuns. A ordem de chamada precisa ser estável entre renders. Chamadas condicionais, dentro de loops ou após retornos antecipados quebram o contrato do reconciler.
// erro estrutural clássicoif (isOpen) { useEffect(() => { // ❌ inválido }, []); }2) useEffect é sincronização com o mundo externo
useEffect não é ferramenta para fluxo de negócio ou derivação de estado. Ele existe para sincronizar com sistemas externos: DOM imperativo, eventos globais, subscriptions, timers, analytics, network side-effects.
Se algo pode ser derivado de props e state, calcule durante o render. Estado derivado em efeito cria inconsistência temporal.
// anti-pattern: estado derivado via efeito// ❌ Evite const [fullName, setFullName] = useState(""); useEffect(() => { setFullName(first + " " + last); }, [first, last]);// correto: derivação no renderconst fullName = first + " " + last;3) Efeitos devem ser idempotentes
Em Strict Mode (dev), efeitos executam duas vezes para detectar efeitos não idempotentes. Código que depende de 'rodar uma vez' está incorreto por definição.
// efeito com cleanup adequadouseEffect(() => { const controller = new AbortController(); fetch("/api/data", { signal: controller.signal }); return () => { controller.abort(); }; }, []);4) Dependências não são sugestão — são contrato
Ignorar eslint-plugin-react-hooks cria closures obsoletas (stale closures). Se um valor é usado dentro do efeito, ele deve estar na lista de dependências ou ser estabilizado.
// stale closure clássicouseEffect(() => { const id = setInterval(() => { console.log(count); // pode ficar desatualizado }, 1000); return () => clearInterval(id); }, []);5) useMemo e useCallback são otimizações, não arquitetura
Memoização excessiva aumenta complexidade cognitiva. Só use quando: (1) evitar recomputação pesada, (2) manter identidade estável para memoização descendente, (3) evitar rerender caro.
6) Estado local é default. Compartilhamento exige fronteira clara
Elevar estado cedo demais cria acoplamento estrutural. Prefira estado local até haver necessidade real de coordenação entre múltiplas áreas.
7) useRef não é estado invisível
useRef é para armazenar valores mutáveis que não causam re-render. Não use como atalho para evitar arquitetura adequada.
// uso correto de ref para valor mutávelconst latestValue = useRef(value); useEffect(() => { latestValue.current = value; }, [value]);8) Custom hooks são APIs de domínio
Um hook deve comunicar intenção de produto. useCheckoutFlow, usePermissionGate, useAutoSaveDraft são contratos semânticos. Isso reduz vazamento de implementação.
// custom hook como boundary de domíniofunction useCheckoutFlow() { const [step, setStep] = useState<"cart" | "payment" | "confirm">("cart"); const next = () => { setStep((s) => s === "cart" ? "payment" : s === "payment" ? "confirm" : s ); }; return { step, next }; }9) Concurrency e transições exigem previsibilidade
Com startTransition e render concorrente, atualizações podem ser interrompidas. Hooks precisam ser determinísticos. Evite efeitos com dependência implícita de ordem temporal.
10) Separação clara: render puro vs side effects
Render deve ser função pura de props + state. Effects conectam o componente ao mundo externo. Misturar ambos gera comportamento difícil de raciocinar sob re-render.
“Os melhores hooks descrevem comportamento de produto com efeitos previsíveis e fronteiras explícitas com o mundo externo.”
— Leonardo DavidChecklist de disciplina com Hooks
// verificação arquiteturalconst hooksChecklist = [ "Hook não é chamado condicionalmente?", "useEffect sincroniza algo externo?", "Não existe estado derivado desnecessário?", "Dependências estão completas?", "Efeito é idempotente?", "Memoização tem justificativa mensurável?", "Custom hook expressa domínio e não detalhe técnico?", ];Dominar Hooks não é memorizar APIs. É entender o modelo mental do React: render puro, efeitos previsíveis, identidade estável e concorrência segura. Quando essa disciplina é aplicada, a base do produto se torna mais previsível, testável e evolutiva.

Escrito por Leonardo David
Engenheiro Full Stack. Atuo construindo produtos de alta performance na intersecção entre frontend, backend e estratégia de produto.