useMemo(fn, deps)- кешує результат обчислення між рендерами, доки залежності не змінились.useCallback(fn, deps)- кешує саму функцію (те саме посилання). По суті,useMemo(() => fn, deps).
const visible = useMemo(
() => todos.filter((t) => matches(t, filter)),
[todos, filter],
);
const handleSelect = useCallback((id) => setSelected(id), []);
Коли вони потрібні:
- Справді дороге обчислення - фільтрація чи сортування тисяч елементів, побудова дерева. Перевірити легко:
console.timeнавколо обчислення; якщо це мілісекунди й більше - є сенс. - Стабільне посилання для дочірнього компонента з
memo- інакше нові об'єкт чи функція на кожен рендер скасовують мемоізацію. - Значення в залежностях ефекту - функція чи об'єкт, створені заново на кожен рендер, перезапускали б
useEffectщоразу.
Коли зайві:
- Прості обчислення (
a + b,items.length, форматування рядка) - мемоізація коштує більше за них. - Колбеки для звичайних DOM-елементів (
<button onClick={...}>) - кнопці байдуже, нова це функція чи ні. - «Про всяк випадок» скрізь - код важче читати, а неправильні залежності створюють баги зі застарілими значеннями.
Важливо: useMemo - оптимізація, а не гарантія. React може скинути кеш, тож код має працювати правильно й без нього.
React Compiler робить цю мемоізацію автоматично на етапі збирання. У проєктах, де він увімкнений, ручні useMemo і useCallback здебільшого прибирають.