Pular para o conteúdo
React

React Hooks: Guia Definitivo 2026

Domine todos os React Hooks com exemplos práticos. De useState ao custom hooks avançados, performance optimization e patterns que empresas top usam em produção.

Gustavo Miranda
22 min de leitura
LinkedIn𝕏X
ReactHooksFrontendPerformanceTypeScript

Por que isso é importante

Domine todos os React Hooks com exemplos práticos. De useState ao custom hooks avançados, performance optimization e patterns que empresas top usam em produção.

O que São React Hooks

Hooks são funções que permitem usar state e lifecycle em componentes funcionais. Lançados no React 16.8, eles substituíram class components como padrão da indústria. Hoje, 100% dos novos projetos React usam hooks exclusivamente.

A regra principal: hooks só podem ser chamados no top level do componente ou dentro de custom hooks. Nunca dentro de loops, condicionais ou funções aninhadas. O React depende da ordem de chamada para manter o state correto entre renders.

useState: Gerenciamento de Estado Local

O hook mais usado. useState declara uma variável de estado que persiste entre re-renders. Retorna um array com o valor atual e uma função setter.

1
Estado primitivo: const [count, setCount] = useState(0). Ideal para números, strings e booleans. O setter pode receber valor direto ou função callback.
2
Estado com objetos: Sempre crie novo objeto com spread: setUser(prev => ({ ...prev, name: "novo" })). Nunca mute o objeto diretamente. React compara por referência, não por valor.
3
Inicialização lazy: Para estado que exige cálculo pesado, passe uma função: useState(() => computeExpensiveValue()). A função executa apenas no primeiro render.
4
Batching automático: React 18+ agrupa múltiplos setStates em um único re-render. Não precisa mais se preocupar com updates em event handlers, timeouts ou promises.

Erro comum com useState

Nunca use o valor antigo para calcular o novo: Use a forma funcional do setter. setCount(count + 1) pode falhar com múltiplas chamadas. setCount(prev => prev + 1) sempre funciona porque usa o valor mais recente.

useEffect: Efeitos Colaterais

O hook mais mal compreendido. useEffect sincroniza seu componente com sistemas externos: APIs, DOM, timers, WebSockets. Não é um lifecycle method. É uma ferramenta de sincronização.

Quando usar useEffect

1
Fetch de dados: Buscar dados de API quando componente monta ou quando dependências mudam. Use AbortController para cancelar requests quando componente desmonta.
2
Event listeners: Adicionar listeners no window/document. Sempre remova no cleanup function para evitar memory leaks.
3
Subscriptions: WebSockets, observadores de interseção, ResizeObserver. O cleanup desconecta quando componente sai da tela.
4
Sincronização com DOM: Manipular elementos diretamente quando React sozinho não consegue (bibliotecas externas, canvas, animações complexas).

Quando NÃO usar useEffect

useEffect desnecessário

Transformar dados para render: Calcule durante o render, não em useEffect. const filtered = items.filter(i => i.active) direto no corpo do componente.
Reagir a eventos: Use event handlers. Click, submit, change — tudo no handler, não em useEffect.
Estado derivado: Se um state depende de outro, calcule no render. Não use useEffect + setState para sincronizar states.
Reset de estado com key: Use key prop para resetar componente ao invés de useEffect + setState.

useRef: Referências Persistentes

useRef cria uma referência mutável que persiste entre renders sem causar re-render quando muda. Dois usos principais: acessar elementos DOM e armazenar valores que não precisam trigger re-render.

1
Referência DOM: const inputRef = useRef(null). Passe como ref={inputRef} no JSX. Acesse com inputRef.current para focus, scroll ou medições.
2
Valor anterior: Armazene o valor do render anterior: prevValueRef.current = currentValue dentro de useEffect. Compara estado atual com anterior sem re-renders extras.
3
Timer IDs: Guarde IDs de setTimeout/setInterval em refs para limpar no cleanup. timerRef.current = setInterval(...)

useMemo e useCallback: Performance

Hooks de memoização evitam recálculos e recriações desnecessárias. Mas atenção: usar memoização em tudo é pior que não usar. Memoize apenas quando há impacto mensurável de performance.

useMemo

Memoiza valores computados

Prós
  • Evita recálculos pesados a cada render
  • Ideal para filtros, sorts e transformações
  • Mantém referência estável para objetos
  • Previne re-renders em componentes filhos
Contras
  • Overhead de memória para guardar cache
  • Comparação de dependências tem custo
  • Desnecessário para cálculos simples

useCallback

Memoiza referência de funções

Prós
  • Estabiliza funções passadas como props
  • Essencial com React.memo em filhos
  • Previne re-renders em listas grandes
  • Necessário para dependências de useEffect
Contras
  • Inútil sem React.memo no componente filho
  • Adiciona complexidade de leitura
  • Array de dependências pode ter bugs

Regra de ouro para memoização

Meça antes de memoizar. Use React DevTools Profiler. Se um componente re-renderiza em menos de 16ms (60fps), memoização não faz diferença perceptível. Foque em listas com 100+ items, cálculos com O(n²) ou componentes que causam layout shift visível.

useContext: Estado Global Sem Props Drilling

useContext consome valores de um Context Provider sem passar props por múltiplos níveis. Ideal para theme, autenticação e preferências do usuário.

O problema: todo componente que consome um context re-renderiza quando qualquer valor dele muda. Solução: divida contexts por domínio (AuthContext, ThemeContext, CartContext). Para estado complexo com atualizações frequentes, prefira Zustand ou Jotai ao invés de Context.

Context vs Zustand vs Redux

Context: State simples, baixa frequência de updates (theme, auth, locale)
Zustand: State médio-complexo, API minimalista, sem boilerplate. Melhor escolha para 90% dos projetos em 2026.
Redux Toolkit: State complexo com muitos reducers, time-travel debugging, ecossistema enterprise.

useReducer: Estado Complexo

Quando useState não basta. useReducer gerencia estado com múltiplas transições relacionadas. Ideal para formulários complexos, state machines e lógica que depende do estado anterior.

O pattern: defina actions como objetos com type e payload. O reducer é uma função pura que recebe state + action e retorna novo state. Em TypeScript, use discriminated unions para type safety completo nas actions.

Custom Hooks: Reutilize Lógica

Custom hooks extraem lógica stateful em funções reutilizáveis. Qualquer função que começa com "use" e chama outros hooks é um custom hook. Esse pattern reduz duplicação e melhora testabilidade.

1
useLocalStorage: Persiste state no localStorage com sincronização automática. Aceita key e valor inicial, retorna [value, setValue] como useState.
2
useFetch: Abstrai fetch com estados de loading, error e data. Inclui AbortController para cleanup automático e retry com exponential backoff.
3
useDebounce: Atrasa updates de valor para inputs de busca. Evita requests excessivos enquanto usuário digita. Timer configurável (300ms padrão).
4
useMediaQuery: Detecta breakpoints para lógica condicional.const isMobile = useMediaQuery("(max-width: 768px)"). Responde a mudanças de viewport em tempo real.
5
useClickOutside: Detecta cliques fora de um elemento ref. Essencial para dropdowns, modals e menus que fecham ao clicar fora.

Hooks do React 19

React 19 trouxe hooks novos que simplificam patterns comuns. Eles reduzem boilerplate e melhoram a experiência do dev.

1
useActionState: Gerencia estado de formulários com server actions. Substitui o pattern manual de loading + error + data state. Integra com progressive enhancement.
2
useFormStatus: Acessa status de submissão do formulário pai sem prop drilling. Ideal para botões de submit que mostram loading spinner.
3
useOptimistic: Atualiza UI instantaneamente antes da resposta do servidor. Reverte automaticamente se a action falhar. UX de apps nativos no browser.
4
use(): Resolve promises e consome contexts condicionalmente. Funciona dentro de loops e ifs, diferente de outros hooks. Integra com Suspense para loading states declarativos.

Patterns Avançados de Performance

Performance em React não é sobre memoizar tudo. É sobre arquitetar componentes que minimizam re-renders onde importa.

1
Composition over memoization: Mova state para baixo. Se apenas um componente usa o state, coloque useState nele, não no pai. Menos componentes re-renderizam.
2
Children as props: Passe componentes como children. O pai pode re-renderizar sem afetar children que não mudaram. Pattern simples e eficaz.
3
Virtualização: Para listas com 1000+ items, use @tanstack/virtual. Renderiza apenas items visíveis na viewport. Transforma O(n) em O(1) para DOM nodes.
4
Code splitting: React.lazy() + Suspense para carregar componentes pesados sob demanda. Reduz bundle inicial e melhora Time to Interactive.

Checklist de Hooks

Boas práticas React Hooks

Hooks sempre no top level (nunca em condicionais ou loops)
Array de dependências completo em useEffect e useMemo
Cleanup function em useEffect para evitar memory leaks
Forma funcional do setter quando novo state depende do anterior
useRef para valores que mudam sem precisar re-render
Memoize apenas quando Profiler mostra gargalo real
Custom hooks para lógica reutilizada em 2+ componentes
Context para state de baixa frequência (theme, auth)
Zustand ou Jotai para state complexo com updates frequentes
TypeScript em todos os hooks para autocompletar e segurança

Próximos Passos

Com hooks dominados, o próximo passo natural é Next.js. Server Components mudam a forma como pensamos sobre data fetching e rendering. E React Native leva seus conhecimentos de hooks direto para apps mobile nativos, sem aprender Swift ou Kotlin.

Domine React na Prática

Aprenda React, Next.js e React Native com projetos reais no bootcamp CrazyStack.