使い方
1. 高コスト計算をメモ化
const result = React.useMemo(() => heavyCalc(n), [n]);
-
ポイント:
n
が変わらない限りheavyCalc
は再実行されず、時間を節約。
2. フィルター済みリストをキャッシュ
const visible = React.useMemo(() => items.filter(f), [items, f]);
- ポイント: 配列や関数が同じなら結果を再利用し、無駄な再計算を防ぐ。
useMemo の役割
レンダーのたびに時間がかかる処理を 覚えておき、必要なときだけ再計算するフック。
-
パフォーマンスを守る
重い計算をむやみに繰り返さない。 -
依存配列で更新を制御
どの値が変わったら再計算するか宣言できる。 -
メモ化が簡単
複雑なキャッシュロジックを書かずに済む。
パフォーマンスを守るとは?
React は状態が変われば全部の関数をもう一度実行します。
その中に 重いループやソート があると、毎回待たされて体感が悪化。
useMemo
に包めば「前回と同じ入力なら古い結果を即返す」ため、レンダーがサクサク動きます。
例:素数判定を重ねて行うコンポーネント
// App.jsx
import React from "react";
// 素数かどうか判定(わざと時間がかかる実装)
function isPrime(num) {
if (num < 2) return false; // 0 と 1 は素数でない
for (let i = 2; i * i <= num; i++) { // √num まで割り算
if (num % i === i) return false; // 割り切れたら素数ではない
}
return true; // 割り切れなければ素数
}
export default function App() {
const [value, setValue] = React.useState(1); // 入力値
const [other, setOther] = React.useState(false); // 無関係な状態
// isPrime が重いのでメモ化
const prime = React.useMemo(() => isPrime(value), [value]); // value が変わった時だけ計算
return (
<div>
<input
type="number"
value={value}
onChange={e => setValue(Number(e.target.value))}
/>
<p>{value} は {prime ? "素数です" : "素数ではありません"}</p>
{/* 無関係なボタン */}
<button onClick={() => setOther(o => !o)}>
レンダー確認ボタン(押しても計算し直さない)
</button>
</div>
);
}
useMemo のベストプラクティス
-
「遅い処理」だけに使う
早い関数まで包むと逆にオーバーヘッドで遅くなる。 -
依存配列を漏れなく書く
使っている変数を全部入れないと古い値を参照してバグのもと。