Obě funkce ukládají něco do mezipaměti napříč renders, aby se to nebylo třeba přepočítávat/znovu vytvářet při každém renders:
useMemo ukládá do mezipaměti vypočítanou hodnotu.useCallback ukládá do mezipaměti identitu funkce (je to useMemo(() => fn, deps)).Existují proto, aby se zabránilo (a) opakování drahé práce a (b) porušení referenční rovnosti, na kterou se spoléhají memoizované komponenty potomků.
function Table({ rows, onSelect }) {
// (a) expensive computation — recompute only when `rows` changes
const sorted = useMemo(() => rows.slice().sort(byName), [rows]);
// (b) stable function identity — so a React.memo child doesn't re-render,
// and effects depending on it don't re-fire
const handleSelect = useCallback(id => onSelect(id), [onSelect]);
return <Grid rows={sorted} onSelect={handleSelect} />;
}
Bez useCallback je handleSelect zcela nová funkce při každém renders. React.memo(Grid) by viděl "novou" vlastnost (prop) a tak či onak by se znovu vykreslit, čímž by se anuloval memoization. Totéž platí pro objekt předaný memoizované komponentě potomka nebo použitý v poli závislostí useEffect.
const x = useMemo(() => a + b, [a, b]); // ❌ pointless — adding is cheaper than memoizing
useMemo/useCallback všude přidává šum a může být dokonce pomalejší. (Kompilátor React 19 může automaticky memoizovat, čímž snižuje potřebu.)