React Hooks: Domine useState, useEffect e os Hooks Essenciais do React Moderno

O que são React Hooks?
Lançados oficialmente no React 16.8 em 2019, os Hooks revolucionaram a forma como escrevemos componentes React. Antes deles, lógica com estado, efeitos colaterais e contexto só era possível em componentes de classe. Hoje, os Hooks permitem que componentes funcionais tenham acesso a todo o poder do React com uma sintaxe mais limpa e intuitiva.
Neste artigo, você vai aprender na prática os Hooks mais importantes do ecossistema React, com exemplos reais e boas práticas para aplicar no seu próximo projeto.
useState: Gerenciando Estado Local
O useState é o Hook mais fundamental. Ele permite adicionar estado a componentes funcionais de forma simples e direta:
import React, { useState } from 'react';
function Contador() {
const [contador, setContador] = useState(0);
return (
<div>
<p>Você clicou {contador} vezes</p>
<button onClick={() => setContador(contador + 1)}>
Incrementar
</button>
</div>
);
}O useState retorna um par: o valor atual do estado e uma função para atualizá-lo. Você pode usar qualquer tipo — números, strings, objetos, arrays. Para estados complexos, lembre-se de sempre criar um novo objeto ao invés de modificar o existente, respeitando o princípio da imutabilidade.
useEffect: Lidando com Efeitos Colaterais
O useEffect unifica os métodos de ciclo de vida que antes existiam em componentes de classe — componentDidMount, componentDidUpdate e componentWillUnmount — em uma única API:
import React, { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
}
fetchUser();
}, [userId]);
if (loading) return <p>Carregando...</p>;
return <h1>{user.name}</h1>;
}O segundo argumento do useEffect é o array de dependências. Ele controla quando o efeito deve ser reexecutado: um array vazio [] executa apenas na montagem do componente; sem array, executa após toda renderização. É essencial também retornar uma função de cleanup para evitar vazamentos de memória, como remover event listeners ou cancelar requisições.
useContext: Compartilhando Dados sem Prop Drilling
O useContext resolve o problema de passar props por múltiplos níveis da árvore de componentes — conhecido como prop drilling:
const TemaContext = React.createContext('claro');
function Botao() {
const tema = useContext(TemaContext);
return <button className={`btn-${tema}`}>Clique aqui</button>;
}
function App() {
return (
<TemaContext.Provider value="escuro">
<Botao />
</TemaContext.Provider>
);
}Com o useContext, qualquer componente na árvore pode acessar o valor do contexto sem recebê-lo como prop, simplificando drasticamente a arquitetura de temas, autenticação e preferências do usuário.
useRef e useMemo: Performance e Referências
O useRef permite acessar elementos do DOM diretamente e manter valores que persistem entre renderizações sem causar re-renderizações desnecessárias:
function InputFocado() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} type="text" />;
}Já o useMemo memoriza valores computacionalmente caros para evitar recálculos em toda renderização:
const totalCompras = useMemo(() => {
return itens.reduce((acc, item) => acc + item.preco * item.quantidade, 0);
}, [itens]);Custom Hooks: Reutilizando Lógica entre Componentes
A verdadeira potência dos Hooks está na possibilidade de criar seus próprios hooks personalizados. Eles permitem extrair lógica de estado e efeitos em funções reutilizáveis que podem ser compartilhadas entre diversos componentes:
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
function MeuComponente() {
const largura = useWindowWidth();
return <p>Largura da tela: {largura}px</p>;
}Custom hooks seguem a convenção de nomenclatura useNomeDoHook e podem usar outros hooks internamente. Eles são a melhor forma de manter seu código DRY (Don't Repeat Yourself) no ecossistema React.
Regras dos Hooks
Existem duas regras fundamentais que você deve sempre seguir ao trabalhar com Hooks:
- Não chame Hooks dentro de loops, condições ou funções aninhadas — eles devem estar sempre no nível superior do componente funcional.
- Não chame Hooks fora de componentes React ou custom hooks — apenas dentro de funções React ou hooks personalizados.
Felizmente, o plugin eslint-plugin-react-hooks detecta automaticamente violações dessas regras durante o desenvolvimento, evitando bugs sutis de renderização.
Conclusão
Os React Hooks transformaram o ecossistema React, tornando o código mais limpo, modular e fácil de testar. Com useState para estado local, useEffect para gerenciar efeitos colaterais, useContext para contexto global e a possibilidade de criar hooks personalizados, você tem todas as ferramentas necessárias para construir aplicações web modernas e escaláveis.
Comece implementando os hooks básicos em seus componentes e, aos poucos, avance para padrões mais complexos como custom hooks e memoização com useMemo e useCallback. O ecossistema React continua evoluindo rapidamente, e dominar os Hooks é hoje uma habilidade essencial para qualquer desenvolvedor frontend.







