Reactのパフォーマンス最適化フックuseMemo
最初に検討するパフォーマンス最適化フックは
useMemoです。
このフックは、リソースを大量に消費する操作の結果を 再レンダリングの間にキャッシュし、それにより不要な重い 計算を避けることができます。このようなキャッシュは メモ化とも呼ばれます。
どのように動作するか見てみましょう。ボタンと
h3見出しを持つコンポーネントを作成しましょう:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
次に、見出しをクリックするとその色がオレンジから
緑に、またはその逆に変わるようにしましょう。まずは
ステートisGreenを設定します:
const [isGreen, setIsGreen] = useState(false);
見出しのstyle属性に色変更の条件を追加し、
クリックハンドラを設定します:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
また、ボタンをクリックすると1ずつ増加する値も あることにしましょう。そのためのステートを 設定します:
const [num, setNum] = useState(0);
ボタンのクリック処理を追加します:
<button onClick={() => setNum(num + 1)}>
clicks
</button>
さらに、numの2乗を返す関数
squareがあるとします。関数の呼び出し結果は
変数resultに格納します:
const result = square(num);
function square(num) {
return num * num;
}
ボタンのテキストにresultを表示させます:
<button onClick={() => setNum(num + 1)}>
clicks: {result}
</button>
結果として、次のようになりました:
ボタンをクリックするとnumの値が変わり、
その後2乗されます。また、見出しをクリックすると
見出しの色が変わります。
コンポーネントは非常に小さく、見出しの色を変えるための クリックでコンポーネント全体が再描画され、それに伴って ボタンに関連する計算も再度行われるにもかかわらず、 すべてが迅速に動作します。ボタンには触れていないにも かかわらずです。もし計算が重く、毎回すべてが 再計算されるとしたらどうなるか想像してみてください。
関数をもう少し重くしてみましょう。これにより、 長時間の計算をシミュレートします:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// 何もしない...
}
return num * num;
}
では、見出しをクリックしてみてください。関数
squareの動作が遅いため(ボタンには触れていないのに)、
見出しの色が変わるのを永遠に待たなければならない
ことになります!
ここでuseMemoフックが役立ちます。これを使用するには、
キャッシュしたい値を計算する関数を第一引数として渡します。
この関数は純粋で、パラメータを受け取ってはいけません。
第二引数には、角括弧内に依存関係、つまり関数のコードに
関与するすべてのリアクティブな値を渡します。
これにより、resultには次のような構造が記述されます:
const result = useMemo(() => square(num), [num]);
もう一度見出しをクリックしてみてください。今度は、
計算に関連するボタンに触れてステートnumの値を
変更しない限り、何も再計算されず、Reactはボタンに
キャッシュされた値を表示するため、見出しの色が
素早く変わります。
Appコンポーネントを作成し、段落を配置してください。
初期値'react'を持つステートtextを設定し、
ステートの値が段落のテキストとして表示されるようにします。
段落がクリックされると、テキストの末尾に感嘆符が追加されるようにします。
初期値0を持つ別のステートnumを設定します。
Appにもう一つ段落を配置します。クリックすると
numが1ずつ増加するようにします。
次に、Appに関数tripleを追加します。
この関数はパラメータとしてnumを受け取り、
その3倍の値を返します。関数の呼び出し結果を
変数resultに格納します。
resultを2番目の段落のテキストとして表示します。
段落を順番にクリックし、感嘆符の追加がどのように遅くなるか
確認してください。
遅い関数tripleをuseMemoでラップして
状況を改善してください。