useCallback
O useCallback
é um hook do React que memoriza funções para evitar que elas sejam recriadas a cada renderização do componente. Isso é especialmente útil para otimizar o desempenho em componentes que recebem funções como props ou que dependem de efeitos complexos.
Para ilustrar esse conceito, vamos criar um exemplo com o tema Cartas com Magia, onde o jogador pode lançar feitiços e cada carta possui um efeito especial. Usaremos o useCallback
para garantir que os efeitos das cartas sejam estáveis, mesmo quando o componente principal for re-renderizado.
Exemplo prático — Grimório de Feitiços ✨
Imagine que você tem um grimório cheio de cartas mágicas. Cada carta lança um feitiço, mas queremos garantir que a função que define o efeito do feitiço não seja recriada desnecessariamente a cada vez que uma nova carta é adicionada ao grimório.
import React, { useState, useCallback } from 'react';
function SpellCard({ name, castSpell }) {
return (
<div style={{ border: '2px solid #a855f7', padding: '10px', margin: '10px' }}>
<h3>{name}</h3>
<button onClick={castSpell}>Lançar Feitiço</button>
</div>
);
}
function SpellBook() {
const [mana, setMana] = useState(100);
const [spells, setSpells] = useState([
{ id: 1, name: 'Bola de Fogo' },
{ id: 2, name: 'Escudo Arcano' },
]);
const castSpell = useCallback((spellName) => {
if (mana >= 10) {
alert(`✨ Você lançou o feitiço: ${spellName}! ✨`);
setMana((prevMana) => prevMana - 10);
} else {
alert('Mana insuficiente!');
}
}, [mana]); // Dependência: mana
const addSpell = () => {
const newSpell = { id: spells.length + 1, name: 'Raio Místico' };
setSpells((prevSpells) => [...prevSpells, newSpell]);
};
return (
<div>
<h2>Grimório de Feitiços ♂️</h2>
<p>Mana: {mana}</p>
<button onClick={addSpell}>Adicionar Carta de Feitiço</button>
<div>
{spells.map((spell) => (
<SpellCard key={spell.id} name={spell.name} castSpell={() => castSpell(spell.name)} />
))}
</div>
</div>
);
}
Como funciona o useCallback?
Neste exemplo, criamos um grimório de feitiços onde o jogador pode lançar feitiços clicando nos botões das cartas. A fun ção castSpell, que exibe um alerta com o nome do feitiço, é envolvida pelo useCallback.
O que isso faz? Mesmo que o grimório (estado) mude quando adicionamos uma nova carta, o React não recria a função castSpell desnecessariamente. Isso evita renderizações extras e melhora o desempenho, especialmente em componentes que recebem funções via props, como no caso da SpellCard.
Dependências do useCallback:
- A função castSpell agora depende do estado mana. Isso significa que a função só será recriada quando o valor de mana mudar.
- Se omitirmos a dependência mana, a função castSpell sempre usará o valor inicial de mana, mesmo que ele seja alterado.
Por que usar useCallback?
Em componentes simples, a recriação de funções geralmente não é um problema. No entanto, em componentes mais complexos — como listas grandes, componentes que usam useEffect, ou quando a função é passada para componentes filhos — a recriação desnecessária pode causar renderizações extras, degradando o desempenho.
No exemplo das cartas mágicas, imagine que você tem centenas de cartas. Se o React recriasse a função de lançar feitiço a cada nova carta adicionada, o desempenho cairia. Com useCallback, garantimos que a função só será recriada quando for realmente necessário.
Quando evitar useCallback?
O useCallback é ótimo para otimizar componentes, mas não deve ser usado de forma excessiva. Se a função não for passada para componentes filhos ou não causar re-renderizações caras, o ganho de performance pode ser insignificante — e o uso desnecessário do hook pode até tornar o código mais complicado de entender.
Conclusão
O useCallback é uma ferramenta valiosa para otimizar o desempenho de aplicações React, especialmente quando trabalhamos com componentes interativos e listas dinâmicas. No exemplo do grimório de feitiços, ele nos permitiu lançar magias sem sobrecarregar a aplicação, mesmo conforme novas cartas eram adicionadas.
Se você estiver criando componentes que lidam com funções passadas como props, ou que precisam de uma performance afinada, o useCallback pode ser o feitiço perfeito para manter sua aplicação rápida e fluída.
Este simplesmente é um dos hooks mais negligenciados e que de fato ajudam e muito, ele é muito útil. Com a versão React Compiler isso deve mudar, diizem que não vai ser mais necessário, mas vamos ver. Tem muita coisa até lá e muito sistema que precisa do useCallback.