useMemo

June 1, 2025

Quanto mais eu trabalho com React, especialmente em features que começam a ficar mais “parrudas”, mais a palavra “performance” começa a piscar na minha cabeça. No começo, a gente não se liga muito nisso, mas depois de um tempo, evitar re-renders desnecessários vira quase um jogo. Uma das coisas que eu precisei entender melhor como otimizar componentes em foi o hook useMemo.

Afinal, o que é useMemo?

Pra ser direto, o useMemo é um hook do React que “memoriza” o resultado de um cálculo pesado. A palavra-chave aqui é resultado. Ele não guarda a função, mas sim o valor que ela retorna.

Imagina que você tem uma função que demora um pouco pra rodar — tipo filtrar uma lista gigante de dados ou fazer uma computação matemática complexa. Sem o useMemo, essa função rodaria toda vez que o seu componente renderizasse de novo. E um componente renderiza por vários motivos, né? Mudança de estado, novas props… qualquer coisinha.

O useMemo entra em cena pra falar: “Opa, calma aí. Se os dados que essa função usa não mudaram, não precisa calcular tudo de novo. Pega aqui o resultado da última vez, que eu guardei pra você”.

É basicamente um cache para o resultado de uma função. Simples assim.

Como a mágica acontece?

A lógica é bem clara. O useMemo precisa de duas coisas:

  1. Uma função de “criação”: É a função que faz o trabalho pesado e retorna o valor que você quer guardar.
  2. Uma lista de dependências: Esse é o pulo do gato. É um array [] onde você coloca todas as variáveis (props, estados, etc.) que a sua função usa pra fazer o cálculo.

Funciona mais ou menos assim:

  • Na primeira renderização: O React executa sua função, pega o resultado e guarda numa “gavetinha”.
  • Nas próximas renderizações: O React olha pra lista de dependências. Ele compara cada item do array com o valor que ele tinha na renderização anterior.
    • Se nada mudou, ele simplesmente pega o resultado que estava na gaveta e te entrega. A sua função nem chega a ser executada.
    • Se pelo menos uma dependência mudou, aí sim o React executa a função de novo, atualiza o valor na gaveta e te entrega o novo resultado.

Vamos ver um exemplo prático. Foi assim que a ficha realmente caiu pra mim:

import React, { useMemo } from "react";

function ProductList({ products, searchTerm }) {
  // A parte pesada é essa filtragem aqui
  const visibleProducts = useMemo(() => {
    console.log("Opa, filtrando a lista de novo... Isso deveria ser raro!");
    return products.filter((product) =>
      product.name.toLowerCase().includes(searchTerm.toLowerCase()),
    );
  }, [products, searchTerm]); // <-- As dependências!

  return (
    <ul>
      {visibleProducts.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Nesse código, a filtragem da lista products só vai acontecer de verdade se a própria lista products mudar ou se o searchTerm for alterado. Se o componente ProductList precisar renderizar de novo por qualquer outro motivo (por exemplo, um estado no componente pai que não tem nada a ver com isso mudou), o React vai pular o filter e reutilizar a lista visibleProducts que já tinha sido calculada. O console.log ali é a prova dos nove – você vai ver que ele não dispara toda hora.

Mas atenção: useMemo não é bala de prata

Aqui foi outra lição importante. Minha primeira reação foi querer sair colocando useMemo em tudo. “Vou otimizar tudo!”.

Usar useMemo tem um custo. O React precisa guardar esse valor em memória e, a cada renderização, precisa comparar as dependências. Para cálculos muito simples e rápidos, o custo de usar o useMemo pode ser maior do que o benefício. Fazer useMemo(() => 2 + 2, []) é um exemplo bobo, mas ilustra o ponto.

Então, a minha regra de bolso passou a ser:

  1. Isso é um cálculo realmente pesado ou caro? (Ex: iterar sobre um array de milhares de itens).
  2. A função está sendo chamada com os mesmos inputs várias vezes, causando re-renders desnecessários?
  3. O valor que estou memoizando é “referencialmente estável”? (Ou seja, estou evitando que um objeto ou array seja recriado a cada render, o que faria componentes filhos renderizarem de novo?).

Se a resposta for “sim” para alguma dessas perguntas, aí o useMemo brilha. Caso contrário, provavelmente é um exagero. No final das contas, ele é uma ferramenta de otimização, e a gente só otimiza o que realmente precisa ser otimizado.