レビュー済み·難易度: 初級·更新: 2026-04-15

useCallback と useMemo の使い分け

useCallback は関数の参照を、useMemo は計算結果をメモ化する。どちらをいつ使うべきかを最小サンプルで比較する。

reactperformance

対応バージョン

react 19typescript 5

前提環境

React hooks の基本(useState, useEffect)を理解していること

概要

フックメモ化する対象再計算のタイミング
useCallback関数の参照依存配列が変わったとき
useMemo計算の結果依存配列が変わったとき

useCallback — 関数参照をメモ化

子コンポーネントに関数を props として渡すとき、親が再レンダリングされるたびに新しい関数参照が生成される。 useCallback を使うと依存値が変わらない限り同じ参照を返す。

import { useState, useCallback, memo } from "react";

// memo でラップされた子コンポーネント
const Button = memo(({ onClick, label }: { onClick: () => void; label: string }) => {
  console.log(`${label} rendered`);
  return <button onClick={onClick}>{label}</button>;
});
Button.displayName = "Button";

export function Counter() {
  const [count, setCount] = useState(0);
  const [other, setOther] = useState(0);

  // useCallback なし → other が変わるたびに新しい参照が生成される
  const incrementWithout = () => setCount((c) => c + 1);

  // useCallback あり → other が変わっても同じ参照を維持
  const incrementWith = useCallback(() => setCount((c) => c + 1), []);

  return (
    <div>
      <p>count: {count} / other: {other}</p>
      <Button onClick={incrementWithout} label="without useCallback" />
      <Button onClick={incrementWith} label="with useCallback" />
      <button onClick={() => setOther((o) => o + 1)}>other++</button>
    </div>
  );
}

useMemo — 計算結果をメモ化

重い計算を毎レンダリング実行しないようにする。

import { useState, useMemo } from "react";

function heavyCalc(n: number): number {
  // 重い処理の模擬
  let result = 0;
  for (let i = 0; i < n * 1000; i++) result += i;
  return result;
}

export function HeavyList({ count }: { count: number }) {
  const [filter, setFilter] = useState("");

  // useMemo なし → filter 変更のたびに heavyCalc が実行される
  // const result = heavyCalc(count);

  // useMemo あり → count が変わったときのみ再計算
  const result = useMemo(() => heavyCalc(count), [count]);

  return (
    <div>
      <input value={filter} onChange={(e) => setFilter(e.target.value)} placeholder="フィルタ" />
      <p>result: {result}</p>
    </div>
  );
}

ポイント

  • memo + useCallback はセットで使うことが多い
  • useMemo は計算コストが高い処理に限定する
  • 依存配列の指定ミスに注意(ESLint の exhaustive-deps ルールを活用する)
  • 過剰なメモ化はコードを複雑にするだけなので、プロファイラで計測してから適用する

注意点

闇雲にメモ化するとかえってコストが増えることがある。計測して必要な箇所にだけ適用すること

関連サンプル