🔖
useMemoを具体例とともに理解する
例えば、1 を 100000000回 足し上げるような関数を実行し、その計算結果を表示するコンポーネントがあるとする。
export const Counter = () => {
// 1 を 100000000回 足し上げる
const heavyComputation = () => {
console.log('Computing...')
let sum = 0;
for (let i = 0; i < 100000000; i++) {
sum += i;
}
return sum;
}
return (
<p>計算結果:{heavyComputation()}</p>
);
}
このコンポーネントをレンダリングしてみると、もちろん、 heavyComputation
は実行されるため Computing...
とログが出力される。
useMemoを使わない場合
ここで、このコンポーネントを ボタンをクリックすると state が変化するように変更する。
そうすると、ボタンをクリックするたびにこのコンポーネントは再レンダリングされるようになる。
export const Counter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
// 1 を 100000000回 足し上げる
const heavyComputation = () => {
console.log('Computing...')
let sum = 0;
for (let i = 0; i < 100000000; i++) {
sum += i;
}
return sum;
}
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment A</button>
<p>計算結果:{heavyComputation()}</p>
</div>
);
}
ボタンをクリックした時の様子を確認してみると、ボタンをクリックするたびに Computing...
とログが出力されていることからコンポーネントが再レンダリングされる度に heavyComputation
が実行されていることがわかる。
useMemoを使う場合
このように何度実行しても計算結果が同じになるような関数がある時、この計算結果を useMemo
を使ってキャッシュすることができる。
// useMemo で計算結果をキャッシュする
const heavyComputation = useMemo(() => {
console.log('Computing...')
let sum = 0;
for (let i = 0; i < 100000000; i++) {
sum += i;
}
return sum;
},[]);
これで再度ボタンをクリックした時の様子を確認してみる。
そうすると state に変化が起きてコンポーネントが再レンダリングされているにも関わらず、 ログ出力は最初のレンダリング時にしか発生していない。
つまり、heavyComputation
の実行は最初の1回だけ実行されていることがわかる。
このように、何度繰り返しても計算結果が同じになるような場合に useMemo
を使うことで不要な関数実行を防ぐことができる。
Discussion