Hooks avançados: useMemo, useCallback e quando não usar
Memoização é bisturi, não tempero: o que useMemo e useCallback realmente fazem (igualdade referencial), os 3 casos legítimos, os erros estruturais e o que muda com o React Compiler.
Existe um rito de passagem em todo time React: alguém descobre useMemo e useCallback, e na semana seguinte o código inteiro está embrulhado neles "por performance". Meses depois, o app não está mais rápido, mas está bem mais difícil de ler. Este artigo é o antídoto: o que esses hooks realmente fazem, quando pagam o próprio custo e quando são ruído.
O problema real: igualdade referencial
Tudo se resume a um detalhe do JavaScript: dois objetos com o mesmo conteúdo não são iguais.
{ a: 1 } === { a: 1 } // false
A cada renderização, funções e objetos criados no corpo do componente são recriados: novas referências. Isso importa em dois lugares exatos:
- Arrays de dependência (
useEffect,useMemo...): dependência que "muda" a cada render dispara o efeito a cada render. - Props de componentes memoizados (
React.memo): prop nova a cada render anula a memoização, o filho re-renderiza sempre.
useMemo (para valores) e useCallback (para funções) existem para estabilizar referências entre renders. Essa é a função deles; "deixar rápido" é consequência ocasional.
Quando usar de verdade
function Relatorio({ vendas, filtro }) {
// ✅ Cálculo caro de verdade: ordena e agrega milhares de itens
const resumo = useMemo(
() => agregarVendas(vendas, filtro), // roda só se vendas/filtro mudarem
[vendas, filtro]
);
// ✅ Referência estável para um filho memoizado
const aoSelecionar = useCallback((id) => {
setSelecionado(id);
}, []);
return <TabelaPesada dados={resumo} onSelect={aoSelecionar} />;
}
const TabelaPesada = React.memo(function TabelaPesada({ dados, onSelect }) {
/* só re-renderiza se dados/onSelect mudarem DE VERDADE */
});
Os três casos legítimos, segundo a própria documentação (react.dev):
- Cálculo comprovadamente caro (meça: dezenas de milissegundos, listas grandes).
- Prop de componente envolvido em
React.memo(senão o memo é inútil). - Dependência de outro hook que precisa de referência estável.
Fora disso, é custo sem retorno: a memoização também custa (memória para o cache, comparação de dependências a cada render, complexidade de leitura). Memoizar x * 2 é pagar pedágio para economizar um centavo.
O erro nº 1: tratar sintoma em vez de causa
Antes de memoizar, pergunte por que o componente re-renderiza tanto. As causas estruturais têm soluções estruturais:
- Estado no lugar errado: estado que só a busca usa morando no topo da página re-renderiza a página inteira a cada tecla. Desça o estado para perto de quem usa.
- Composição que protege: filhos passados via
childrennão re-renderizam quando o pai muda de estado. Muitas "otimizações" viram desnecessárias com o componente desenhado certo. - Contexto gordo: um Context com dez valores re-renderiza todos os consumidores quando um muda (assunto do quarto artigo desta série).
Memoização em cima de arquitetura ruim é analgésico para dor crônica.

Custom hooks: o hook avançado que sempre vale
Enquanto useMemo é ferramenta de exceção, extrair custom hooks é ferramenta de todo dia: pega a lógica com estado (busca, debounce, formulário, permissões) e a move para uma função nomeada e testável:
function useBuscaDebounced(termo, delay = 300) {
const [resultado, setResultado] = useState([]);
useEffect(() => {
const t = setTimeout(async () => {
setResultado(await buscar(termo));
}, delay);
return () => clearTimeout(t); // cancela a busca anterior
}, [termo, delay]);
return resultado;
}
// No componente, a intenção vira uma linha:
const produtos = useBuscaDebounced(termo);
O componente volta a contar a história da interface; a mecânica vira módulo reutilizável. É a mesma separação de responsabilidades de sempre, em escala de componente.
E o React Compiler?
O elefante da sala: o React Compiler (integrado ao React 19+) memoiza automaticamente, tornando a maior parte dos useMemo/useCallback manuais desnecessária em código que segue as regras dos hooks (react.dev/learn/react-compiler). A direção do framework é clara: memoização é detalhe do compilador, não decoração do desenvolvedor. Mais um motivo para não espalhá-los por reflexo: código limpo hoje é código que o compilador otimiza melhor amanhã.
A régua prática
- Meça antes (React DevTools Profiler): onde o tempo realmente vai?
- Corrija estrutura primeiro: estado no lugar certo, composição, contexto fatiado.
- Memoize o que sobrou com medição comprovando, e comente por quê.
- Deixe o resto simples: legibilidade é a otimização que paga todos os dias.
Auditar performance de front React com esse método (medir, restructurar, memoizar por último) é parte do nosso serviço de Desenvolvimento Web, Mobile e Desktop, junto com as métricas de campo que provam o resultado.
Seu app está cheio de useMemo "por garantia"? Cole um componente na conversa com a IA da Rabelo Digital, aqui no canto da tela, e ela diz o que fica e o que sai. Sem formulário, sem espera.


Deixe um Comentário