Hooks avançados: useMemo, useCallback e quando não usar

Hooks avançados: useMemo, useCallback e quando não usar

Robson Rabelo - 12 de julho de 2026 - 0 visualizações

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:

  1. Arrays de dependência (useEffect, useMemo...): dependência que "muda" a cada render dispara o efeito a cada render.
  2. 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):

  1. Cálculo comprovadamente caro (meça: dezenas de milissegundos, listas grandes).
  2. Prop de componente envolvido em React.memo (senão o memo é inútil).
  3. 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 children nã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.

Hooks de memoização: quando valem o custo

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

  1. Meça antes (React DevTools Profiler): onde o tempo realmente vai?
  2. Corrija estrutura primeiro: estado no lugar certo, composição, contexto fatiado.
  3. Memoize o que sobrou com medição comprovando, e comente por quê.
  4. 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.


Leia também

Compartilhar:

Deixe um Comentário

Categorias

Posts Recentes