どちらも render 間で何かを cache し、毎回再計算または再生成されないようにします。
useMemoは計算済みの値を cache します。useCallbackは関数の identity を cache します(useMemo(() => fn, deps)と同等です)。
これらは、(a) 高コストな処理の繰り返しを避けること、(b) memoized child が依存する referential equality を壊さないこと、のためにあります。
jsx
どちらも render 間で何かを cache し、毎回再計算または再生成されないようにします。
useMemo は計算済みの値を cache します。useCallback は関数の identity を cache します(useMemo(() => fn, deps) と同等です)。これらは、(a) 高コストな処理の繰り返しを避けること、(b) memoized child が依存する referential equality を壊さないこと、のためにあります。
function Table({ rows, onSelect }) {
// (a) 高コストな計算 — `rows` が変わったときだけ再計算する
const sorted = useMemo(() => rows.slice().sort(byName), [rows]);
// (b) 安定した function identity — React.memo の child が再 render されず、
// それに依存する effect も再実行されないようにする
const handleSelect = useCallback(id => onSelect(id), [onSelect]);
return <Grid rows={sorted} onSelect={handleSelect} />;
}
useCallback がないと、handleSelect は render のたびに新しい関数になります。React.memo(Grid) は「新しい」prop を受け取ったと判断し、結局再 render してしまいます。memoized child に渡す object や、useEffect の dependency array に入れる object でも同じ問題が起きます。
const x = useMemo(() => a + b, [a, b]); // ❌ 無意味 — 足し算は memoize より安い
useMemo / useCallback の乱用はノイズを増やし、かえって遅くなることもあります。(React 19 の compiler は自動 memoization が可能で、必要性を下げます。)