最新のReact hooksに追いつく useMemo編
最新のReact hooksに置いていかれたフロントエンドエンジニアが最新のhooksに追いつくためのブログです。3回目useMemoについてです。ここら辺から身に覚えがなくなってきました、、(笑)
useMemoとは
useMemoは、一言でいうと **計算結果を保存しておいてくれるメモ** です。Reactのレンダー時に同じ計算を繰り返し行わないように値など保持することができ、必要な時には再計算してくれます!Memoとつくだけあって意味合いとしてはわかりやすいですかね?実際の構文や使い方を見ていきましょう!
useRefの書き方
useRefの書き方は基本的にはuseStateと一緒です。
const memoizedValue = useMemo(() => {
// 計算処理
return 結果;
}, [依存値]);
書き方自身はuseEffectのときのように、第1引数と第2引数を渡す必要があります。
- 第1引数:計算処理
- 第2引数:依存配列
useEffectのように第2引数が計算を行うか否かにかかわってきそうな雰囲気を感じますね。
お気づきの通り、依存配列内の変数が変更されたときにのみ計算が行われます。
配列が空の場合は、初回レンダー時のみ計算が行われます。
useMemoの使い方
すごい簡単な例を見ていきましょう!
import { useState } from "react";
export default function Example() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
// 重い計算をシミュレーション
const double = (() => {
console.log("重い計算を実行中...");
let i = 0;
while (i < 1000000000) i++; // 無駄に重い処理
return count * 2;
})();
return (
<div>
<p>結果: {double}</p>
<button onClick={() => setCount(count + 1)}>count + 1</button>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="文字を入力してみよう"
/>
</div>
);
}
doubel関数で重ための計算を行っていますが、この関数にuseMemoを使っています。useMemoを使わない場合、input要素のonChangeイベントが発火される(1文字でも入力などがある)と常にstateが変更されレンダーが走るためdoubleを何度も実行することになります。
ですが、今回はuseMemoを使っているおかげで重たい計算を毎レンダー行わなくて済むようになっています。つまり、doubleが実行されるのはcountが変更されるイベント(button要素のクリック)が発火したときのみになります!
結構すごいですよね(笑)
useEffectとの違い
ここまで話を聞いて、あれなんかuseEffectと似ているな、とか、useEffectだけでいいんじゃないと思った方いませんか?!実は私が勉強していてそう思っていました(笑)
ここではuseMemoとuseEffectの違いをしっかり押さえます。
結論:動きは似ているが目的とタイミングは全く違う
useMemoとuseEffectは依存配列によって実行されるタイミングが変わるという面では似ていますが、目的と実際のタイミングは全く違います。
ざっくり比較表
| 項目 | useEffect | useMemo |
|---|---|---|
| 目的 | 副作用(=レンダー後に何かする) | 計算結果をキャッシュ(=レンダー中に使う) |
| 実行タイミング | レンダーのあと | レンダーの前 |
| 返り値 | なし(関数の実行) | 計算結果(値を返す) |
| 主な用途 | API呼び出し・DOM操作・イベント登録など | 計算結果のメモ化・再計算の最適化 |
| 依存配列の意味 | 副作用を再実行するタイミング | 再計算を行うタイミング |
このような形で、「レンダー後にAPIを叩いたり、イベントを登録する」なら useEffect、
「レンダー時に重い計算結果を再利用したい」なら useMemoを使うようにしましょう!
まとめ
ということで今回はuseMemoについてまとめてみました。必要な時だけ計算を再度実行することができるフックになっていましたね、とても便利な感じがします!
でも1つ注意点があって、何でもかんでもuseMemoを使うと、「メモ化の処理のコスト」が増えたり、コードの可読性が落ちたりするため逆効果になることもあります。
なので、重たい計算や頻繁にレンダーが行われるようなコンポーネントにのみ使うとよいのかもしれませんね!
それでは、次のuseId編でお会いしましょう
Discussion