useMemo do React js
Como funciona o useMemo do React? Guia prático com exemplos
Você já imaginou se o React pudesse guardar o resultado de uma conta para não precisar fazê-la novamente toda vez que a tela fosse atualizada? É justamente essa uma das funções do useMemo.
Neste guia, você vai aprender o que é o useMemo, como ele funciona por trás dos panos, quando vale a pena utilizá-lo e quais erros evitar. Tudo com exemplos de código que você poderá testar no seu próprio projeto React.
1. O que é o useMemo no React?
O useMemo é um Hook do React que permite guardar o resultado de um cálculo entre as renderizações de um componente.
Mas o que significa guardar um resultado?
Imagine que você precisa somar os números de uma lista. Se a lista tiver milhares de números, essa conta poderá levar algum tempo. Se nada que afete essa conta mudar, talvez seja desnecessário repetir o mesmo trabalho.
O useMemo permite que o React reutilize o resultado anterior enquanto as informações das quais o cálculo depende continuarem iguais.
Imagine que você fez uma conta na calculadora e anotou o resultado em um caderno. Na próxima vez que precisar do mesmo resultado, você consulta o caderno em vez de fazer a conta novamente.
O useMemo funciona de maneira parecida: ele guarda um resultado para que possa ser reutilizado.
A palavra memo vem de memoização, uma técnica de programação que consiste em guardar resultados de cálculos para reutilizá-los quando as entradas forem as mesmas.
Importante: o useMemo não torna qualquer componente automaticamente mais rápido. Ele é uma ferramenta de otimização e deve ser usado quando existe uma razão para isso.
2. Para que serve o useMemo?
O useMemo é útil principalmente quando um componente realiza cálculos que podem ser caros ou quando você precisa manter a mesma referência de um valor entre renderizações.
Exemplo 1: calcular o total de uma lista
Imagine um aplicativo de compras com centenas de produtos. Para mostrar o preço total, o aplicativo precisa somar os valores dos produtos.
Se o usuário alterar uma informação que não interfere nos preços, como o tema da tela, você pode evitar repetir esse cálculo, desde que suas dependências continuem iguais.
Exemplo 2: filtrar uma lista grande
Imagine uma lista com milhares de nomes. Você quer mostrar apenas os nomes que contêm determinada palavra.
Se a lista e o texto de pesquisa não mudarem, o useMemo poderá reutilizar a lista filtrada que já foi calculada.
Antes de pensar em useMemo, pergunte: este cálculo realmente está causando lentidão? Para contas simples, como somar dois números, normalmente não é necessário usá-lo.
3. Entenda primeiro o que é uma renderização
Para entender o useMemo, precisamos conhecer uma palavra importante do React: renderização.
Renderizar é quando o React executa o componente para descobrir como a interface deve ficar naquele momento.
Por exemplo, quando um estado muda, o React normalmente executa novamente o componente para atualizar a interface.
Veja um componente simples:
Exemplo: um contador
Este código cria um botão que aumenta um número cada vez que você clica nele.
import { useState } from 'react';
function Contador() {
const [numero, setNumero] = useState(0);
return (
<div>
<p>Numero: {numero}</p>
<button onClick={() => setNumero(numero + 1)}>
Aumentar
</button>
</div>
);
}
export default Contador;
Entendendo o código
- useState(0): cria um estado inicial com o valor zero.
- setNumero: é a função usada para pedir ao React que atualize o estado.
- onClick: executa uma função quando o botão recebe um clique.
- numero + 1: calcula o próximo valor do contador.
Quando você clica no botão, o estado muda e o React executa novamente o componente para mostrar o novo número.
É durante essas novas execuções que um cálculo feito diretamente no corpo do componente pode acabar sendo repetido.
4. Como o useMemo funciona por trás dos panos?
O useMemo recebe duas coisas:
- Uma função que realiza o cálculo.
- Uma lista com as dependências que influenciam esse cálculo.
As dependências são os valores que o React deve observar para saber se precisa calcular novamente.
const resultado = useMemo(() => {
return fazerCalculo();
}, [dependencia]);
A função dentro do useMemo calcula o resultado. A lista entre colchetes informa quais valores podem fazer esse resultado precisar ser atualizado.
Vamos acompanhar o que acontece em três situações.
O React ainda não tem um resultado guardado para esse uso do Hook. Então executa a função e guarda o resultado.
O React compara os novos valores com os valores anteriores. Se alguma dependência mudou, ele executa a função novamente e guarda o novo resultado.
O React pode reutilizar o resultado guardado, sem precisar executar novamente aquele cálculo.
Essa comparação usa a identidade de cada valor por meio de Object.is. Para números e strings, isso geralmente se comporta como esperamos. Para objetos e funções, a identidade da referência também importa.
O React trata o resultado memorizado como uma otimização, não como armazenamento garantido para sempre. Em situações específicas, ele pode descartar esse resultado. Por isso, nunca dependa do useMemo para preservar dados importantes ou garantir que um cálculo aconteça apenas uma vez em toda a vida do aplicativo.
5. Primeiro exemplo prático: somando produtos
Vamos criar um componente que calcula o valor total de três produtos. Também teremos um contador separado para demonstrar que nem toda mudança de estado precisa provocar um novo cálculo do total.
Código completo
import { useMemo, useState } from 'react';
function Carrinho() {
const [cliques, setCliques] = useState(0);
const produtos = [
{ nome: 'Teclado', preco: 150 },
{ nome: 'Mouse', preco: 80 },
{ nome: 'Monitor', preco: 900 }
];
const total = useMemo(() => {
return produtos.reduce(
(soma, produto) => soma + produto.preco,
0
);
}, []);
return (
<div>
<h2>Meu carrinho</h2>
<p>Total: R$ {total.toFixed(2)}</p>
<p>Cliques: {cliques}</p>
<button
onClick={() => setCliques(cliques + 1)}
>
Contar clique
</button>
</div>
);
}
export default Carrinho;
Passo a passo da explicação
Passo 1 — Criamos o estado. A variável cliques guarda quantas vezes o botão foi clicado. Ela não interfere no preço dos produtos.
Passo 2 — Criamos os produtos. Cada produto tem um nome e um preço.
Passo 3 — Calculamos o total. O método reduce percorre a lista e soma os preços.
Passo 4 — Guardamos o resultado. O useMemo pode reutilizar o total quando suas dependências não mudam.
Passo 5 — Atualizamos o contador. O botão altera os cliques, mas isso não muda os preços.
A lista de produtos foi criada dentro do componente, mas o useMemo usa uma lista de dependências vazia. Isso só é adequado aqui porque estamos tratando os produtos como dados fixos, que não mudam durante a execução normal do componente.
Em um carrinho real, no qual os produtos podem ser adicionados, removidos ou ter seus preços alterados, você precisa usar dependências que representem corretamente essas mudanças. Uma lista vazia poderia deixar o total desatualizado.
Resultado esperado
Meu carrinho
Teclado: R$ 150,00
Mouse: R$ 80,00
Monitor: R$ 900,00
Total: R$ 1130,00
Cliques: 0, depois 1, 2, 3...
Ao clicar em “Contar clique”, o contador muda. Como os preços continuam iguais, o React pode reutilizar o total memorizado.
Entretanto, a soma de apenas três produtos é muito rápida. Este exemplo ensina o funcionamento do Hook, mas não demonstra necessariamente um ganho de desempenho perceptível.
6. Segundo exemplo prático: filtrando uma lista
Agora vamos imaginar uma lista de tarefas. O usuário pode escrever uma palavra para encontrar tarefas específicas e também pode aumentar um contador independente.
O useMemo poderá reutilizar a lista filtrada quando nem a lista de tarefas nem o texto da pesquisa tiverem mudado.
Código completo
import { useMemo, useState } from 'react';
const tarefasIniciais = [
'Estudar React',
'Aprender useMemo',
'Praticar JavaScript',
'Criar um projeto'
];
function ListaTarefas() {
const [busca, setBusca] = useState('');
const [cliques, setCliques] = useState(0);
const tarefasFiltradas = useMemo(() => {
return tarefasIniciais.filter((tarefa) =>
tarefa.toLowerCase().includes(
busca.toLowerCase()
)
);
}, [busca]);
return (
<div>
<h2>Minhas tarefas</h2>
<input
value={busca}
onChange={(evento) => setBusca(evento.target.value)}
placeholder="Pesquisar tarefa"
/>
<ul>
{tarefasFiltradas.map((tarefa) => (
<li key={tarefa}>
{tarefa}
</li>
))}
</ul>
<p>Cliques: {cliques}</p>
<button
onClick={() => setCliques(cliques + 1)}
>
Aumentar contador
</button>
</div>
);
}
export default ListaTarefas;
Entendendo as partes importantes
- tarefasIniciais: guarda a lista de tarefas fora do componente, evitando criar uma nova lista em cada renderização.
- busca: guarda o texto digitado no campo de pesquisa.
- filter: cria uma nova lista contendo apenas as tarefas que combinam com a pesquisa.
- toLowerCase: transforma o texto em letras minúsculas, facilitando a comparação sem diferenciar maiúsculas de minúsculas.
- includes: verifica se o texto pesquisado aparece no nome da tarefa.
- [busca]: informa ao React que o cálculo depende do texto pesquisado.
- map: transforma cada tarefa filtrada em um elemento da lista na tela.
Resultado esperado
Se você digitar: React
- Estudar React
Se você digitar: JavaScript
- Praticar JavaScript
Se você clicar em “Aumentar contador”, o contador muda. Como a pesquisa continua igual, o resultado do filtro pode ser reutilizado.
Neste caso, a lista é pequena, então o ganho provavelmente será mínimo. Em listas muito grandes ou com filtros caros, a otimização pode ser mais útil.
7. O que são as dependências do useMemo?
As dependências são os valores que o React compara para decidir se pode reutilizar o resultado anterior ou se precisa calcular novamente.
Elas ficam dentro de um array, que é uma lista escrita entre colchetes.
Exemplo 1: uma dependência
const dobro = useMemo(() => {
return numero * 2;
}, [numero]);
Se numero mudar, o React recalcula o dobro. Se ele continuar igual, o React poderá reutilizar o resultado.
Exemplo 2: duas dependências
const precoFinal = useMemo(() => {
return preco * quantidade;
}, [preco, quantidade]);
Aqui, o cálculo depende do preço e da quantidade. Se qualquer um deles mudar, o resultado será recalculado.
Inclua todas as variáveis reativas usadas pelo cálculo e que são definidas no componente, seguindo as regras de dependências do React. O recurso ESLint do plugin oficial de Hooks pode ajudar a encontrar dependências ausentes.
8. O que acontece se você usar useMemo sem dependências?
Existem diferenças importantes entre escrever uma lista vazia e não fornecer uma lista de dependências.
| Forma | Comportamento |
|---|---|
[] |
O cálculo é feito na renderização inicial e o resultado normalmente é reutilizado nas renderizações seguintes, enquanto o React mantiver a memorização. |
[valor] |
O cálculo é refeito quando o valor muda. |
| Sem o segundo argumento | O cálculo é executado novamente em cada renderização. |
Veja um exemplo sem a lista de dependências:
const resultado = useMemo(() => {
return calcularAlgo();
});
Como não existe uma lista de dependências, o React não tem uma lista de valores para comparar e reutilizar o resultado entre renderizações.
Nesse caso, o useMemo geralmente não oferece a economia de cálculo que você esperava. Se não existe uma necessidade de memoização, prefira calcular diretamente.
9. Qual é a diferença entre useMemo e useCallback?
Os dois Hooks ajudam a evitar trabalhos desnecessários, mas guardam coisas diferentes.
useMemo
É usado para memorizar o resultado de uma função.
const dobro = useMemo(() => {
return numero * 2;
}, [numero]);
useCallback
É usado para memorizar a própria função, mantendo a mesma referência enquanto as dependências não mudarem.
const mostrarMensagem = useCallback(() => {
console.log('Olá!');
}, []);
Pense assim: o useMemo guarda o resultado da conta; o useCallback guarda a função que faz a conta.
Essa diferença importa especialmente quando você passa funções para componentes filhos otimizados com memo, pois uma nova referência de função pode fazer o filho renderizar novamente.
10. Qual é a diferença entre useMemo e useEffect?
Esses Hooks têm objetivos diferentes e não devem ser usados como se fossem a mesma coisa.
| Hook | Para que serve |
|---|---|
useMemo |
Memoriza o resultado de um cálculo durante as renderizações. |
useEffect |
Sincroniza o componente com sistemas externos, como uma conexão, uma API ou um evento do navegador. |
Por exemplo, para calcular o total de uma lista, o useMemo pode ser adequado. Para conectar um componente a um serviço externo e limpar a conexão quando necessário, useEffect pode ser a ferramenta apropriada.
Não use useEffect apenas para calcular um valor que pode ser obtido diretamente das propriedades e do estado durante a renderização. Isso pode adicionar uma renderização desnecessária.
11. Erros comuns ao usar useMemo
Erro 1: usar useMemo para qualquer cálculo
Memorizar também tem um custo: o React precisa guardar o resultado e comparar as dependências.
Para uma conta simples, esse trabalho extra pode não trazer vantagem.
Como resolver: calcule diretamente os valores simples e use useMemo quando existir uma necessidade real de otimização.
Erro 2: esquecer uma dependência
Imagine que o cálculo utiliza preco, mas a lista de dependências contém apenas quantidade.
// Incorreto: preco também afeta o resultado.
const total = useMemo(
() => preco * quantidade,
[quantidade]
);
Se o preço mudar e a quantidade continuar igual, o resultado poderá ficar desatualizado.
Como resolver: inclua as duas dependências.
const total = useMemo(
() => preco * quantidade,
[preco, quantidade]
);
Erro 3: alterar um array ou objeto diretamente
Imagine que você tem uma lista de produtos e altera um preço dentro dela sem criar um novo array ou atualizar o estado corretamente.
O React pode não perceber a mudança da maneira esperada, pois objetos e arrays são comparados por referência nas dependências.
Como resolver: atualize os dados de forma imutável, criando novas referências quando os dados realmente mudarem.
// Exemplo de atualização imutável de um array.
const novosProdutos = produtos.map(
(produto) =>
produto.id === idAlterado
? { ...produto, preco: novoPreco }
: produto
);
Erro 4: usar useMemo para executar efeitos colaterais
A função passada ao useMemo deve ser pura: ela deve calcular e devolver um resultado, sem fazer ações externas como enviar requisições, alterar o DOM diretamente ou atualizar estados.
Como resolver: mantenha os cálculos dentro do useMemo e utilize as ferramentas apropriadas para ações externas.
Erro 5: chamar useMemo dentro de um if ou de um loop
Os Hooks do React devem ser chamados no nível principal do componente ou de outro Hook, respeitando sempre a mesma ordem.
Incorreto:
if (ativo) {
const resultado = useMemo(
() => calcular(),
[]
);
}
Correto:
const resultado = useMemo(
() => ativo ? calcular() : null,
[ativo]
);
Agora o Hook é chamado em todas as renderizações, na mesma posição. Quando ativo muda, o React pode calcular o novo resultado.
12. Boas práticas para usar useMemo
- Meça o desempenho antes de otimizar. Use as ferramentas de desenvolvimento do navegador ou o React Profiler para encontrar cálculos realmente custosos.
- Use dependências corretas. Não omita valores utilizados pelo cálculo.
- Mantenha os cálculos puros. A função deve devolver um resultado sem provocar efeitos externos.
- Prefira código simples. Não adicione useMemo se ele não resolver um problema real.
- Evite dependências criadas novamente a cada renderização. Objetos e arrays novos podem fazer o React recalcular o valor.
- Não dependa da memorização para manter dados importantes. O resultado deve poder ser calculado novamente quando necessário.
O React Compiler, quando habilitado e configurado no projeto, pode realizar várias otimizações automaticamente. Por isso, nem sempre é necessário adicionar useMemo manualmente. A decisão depende da configuração do projeto e das necessidades de desempenho.
13. Exercício prático
Agora é sua vez de praticar. Crie um componente que calcula o preço total de uma compra.
- Crie um estado chamado
preco, com valor inicial 20. - Crie um estado chamado
quantidade, com valor inicial 2. - Use useMemo para calcular
preco * quantidade. - Crie botões para aumentar a quantidade e o preço.
- Coloque as duas variáveis na lista de dependências.
Uma possível solução
import { useMemo, useState } from 'react';
function Compra() {
const [preco, setPreco] = useState(20);
const [quantidade, setQuantidade] = useState(2);
const total = useMemo(
() => preco * quantidade,
[preco, quantidade]
);
return (
<div>
<p>Preço: R$ {preco.toFixed(2)}</p>
<p>Quantidade: {quantidade}</p>
<p>Total: R$ {total.toFixed(2)}</p>
<button
onClick={() => setPreco(preco + 5)}
>
Aumentar preço
</button>
<button
onClick={() => setQuantidade(quantidade + 1)}
>
Aumentar quantidade
</button>
</div>
);
}
export default Compra;
Teste mental: se o preço for R$ 20 e a quantidade for 2, o total será R$ 40. Se a quantidade passar para 3, o total será R$ 60.
Como o preço e a quantidade estão nas dependências, o cálculo será atualizado quando qualquer um desses valores mudar.
Nesse exercício, o cálculo é simples e o useMemo não é necessário para obter um bom desempenho. Ele foi utilizado para você praticar seu funcionamento.
14. Resumo: o que você precisa lembrar
- O useMemo memoriza o resultado de um cálculo entre renderizações.
- Ele pode evitar cálculos repetidos quando suas dependências continuam iguais.
- Quando uma dependência muda, o React recalcula o resultado.
- A lista de dependências deve incluir os valores reativos utilizados pelo cálculo.
- Uma lista vazia indica que o cálculo não depende de valores reativos variáveis do componente.
- Sem o segundo argumento, a função é executada novamente em cada renderização.
- O useMemo não substitui useEffect, useState ou useCallback.
- Não use memoização para qualquer conta pequena nem para armazenar dados importantes.
- O resultado memorizado é uma otimização, não uma garantia permanente.
15. Conclusão
Agora você conhece a ideia central do useMemo: guardar o resultado de um cálculo para que ele possa ser reutilizado quando as dependências não mudarem.
Você também aprendeu a escrever o Hook, identificar suas dependências, filtrar listas, calcular totais e evitar erros comuns.
O segredo é não sair adicionando useMemo em todos os componentes. Primeiro entenda o que o código faz, depois identifique se existe um problema de desempenho e só então escolha a otimização adequada.
Para continuar aprendendo, pratique os exemplos deste artigo e consulte a documentação oficial do React para conhecer os detalhes e as recomendações mais recentes.
Documentação oficial: useMemo — React.
Quer ampliar seus conhecimentos em programação?
Se você gostou de aprender como o useMemo funciona e deseja continuar estudando programação, conheça o curso Torne-se um Programador Fullstack e domine o mercado digital!
A proposta informada do curso é ensinar programação do zero ao nível profissional por meio de um método próprio, oferecido por uma escola de programação da América Latina.
O que a descrição informa:
- Conteúdo voltado ao aprendizado de programação.
- Proposta de estudo do nível iniciante ao profissional.
- Método de ensino próprio, conforme a descrição fornecida.
Se você está estudando React, avalie a grade do curso para verificar se os conteúdos oferecidos correspondem ao que deseja aprender. A descrição disponível não especifica quais módulos de React estão incluídos.
Conhecer o curso →Transparência: este artigo contém um link de afiliado. Podemos receber uma comissão se você realizar uma compra por meio desse link, sem custo adicional para você.
.png)
Comentários
Postar um comentário