【React入門】絶対に理解させる(たい)useMemo【初学者向け】
まえがき
React Hooksの中の一つ、useMemo
について解説する。厳密で難しい話をするのではなく、理解させることを目的としている。
対象読者
- React勉強中の方
-
useState
はギリいけるぞって方
useMemoって何
- 重たい処理・計算結果の値を保持して、無駄な計算をしないようにするためのHooks
-
パフォーマンスを向上させる目的のHooksであるから、
useMemo
がないと実装できないってことは基本的にない
処理のサンプルコード
まず重い処理をするコードを見てくれ
const culc = (x: number, y: number) => {
let i = 0;
while (i < 10000) {
console.log("重い処理だよ");
i++;
}
return x * y;
};
この関数は重たい処理をして、結果的に引数の二つの数値の積を返すぞ
useMemo
を利用しない場合
次に、メモ化せずにこの関数の返り値を使うコードを見てくれ
const [x, setX] = useState<number>(10);
const [y, setY] = useState<number>(20);
const result = culc(x, y);
ごく普通の実装だ。この状態で、同じ画面にあるx
,y
の増減に全く関係ないボタン(Stateを変更する)を押してみる。
(自ブログの開発画面です)
x
,y
の値が全く変わっていないにもかかわらず、ボタンを押すたびに毎回関数が実行されてconsole
が表示されている。これは明らかに不要な実行である。
このように、useMemo
を利用していないresult
は、コンポーネントが再レンダリングされるたびに計算される。
再レンダリングって何
- 画面を更新(再描画)するために、JavaScriptをもう一回読み込み直すことだぞ
- 基本的に以下のタイミングで再レンダリングが走るぞ
- 自コンポーネントの
Props
が更新された時 - 自コンポーネントの
State
が変更された時 ← 今回はボタンを押してState
が変更されたからこれ - 親コンポーネントが再レンダリングされた時
- 自コンポーネントの
useMemo
を利用した場合
では、useMemo
を利用して関数の返り値をメモ化(保持)するコードを見てくれ
const [x, setX] = useState<number>(10);
const [y, setY] = useState<number>(20);
const memoResult = useMemo(() => culc(x, y), [x, y]);
この状態で、同じ画面にあるx
,y
の増減に全く関係ないボタン(Stateを変更する)を押してみる。
すると、全くconsole
が表示されない。つまり、関数が実行されていないということになる。
本来、x * y
を計算するというこの関数は、x
,y
のどちらも変更がない場合は、再レンダリングの際にいちいち再計算する必要がないので、これで不要な処理をスキップし、パフォーマンスを向上させることができた。
もちろんx
,y
が変更される場合(x
,y
を変化させるボタンの押下時など)はmemoResult
の値は再計算される。
一般化した使い方の例
const memoResult = useMemo(() => {
// ここに処理を書く
}, [依存する変数をここに並べる(依存配列という)]);
- 依存する変数が変わらない限り、処理は実行されないぞ
- 処理が重たい時に効果を発揮するぞ(再計算が不必要な時にスキップされるため)
- 処理に使う変数を依存配列に入れるぞ(過不足なく入れることが重要)
依存配列に何を入れるべきか
const memoResult = useMemo(() => {
let i = 0;
while (i < 10000) {
console.log("メモされてる方");
i++;
}
return x * y;
}, [x, y]);
もしこのコードの依存配列が[x]
のみだったら、もしy
のみが変更された時、useMemo
の処理が実行されないのでx * y
が更新されない。これは間違った実装である。
逆に、依存配列が[x, y, z]
であったら、z
のみが変更された場合にもuseMemo
の処理が実行される。しかし、計算結果はx * y
であるから、計算結果の変化は全くない。つまり依存配列にz
は必要なく、間違った実装である。
よって、関数に必要である変数を過不足なく依存配列に入れる必要がある。
まとめ
-
useMemo
はReactのHooksで、計算結果をメモ化することでパフォーマンスを向上させる -
useMemo
を使わない場合、コンポーネントが再レンダリングされるたびに計算が実行される -
useMemo
を使用すると、指定した依存配列が変わらない限り、以前の計算結果を再利用する -
useMemo
は、重い計算処理が頻繁に行われる場合や、同じ結果が再利用できる場合に使用すると効果的
このようにして、useMemo
を使うことでReactコンポーネントのパフォーマンスを向上させることができるぞ🚗
Discussion