
初心者向け、React.useMemoっていつ使えばいいの?
アプリケーションの規模が大きくなると、パフォーマンスの問題が顕在化してきます。
Reactは非常によく最適化されており、そのままでも高速ですが、コードをさらに高速化するためにReactが提供する手段を知っておくことが重要です。
そのような手段の1つがReact.useMemoフックと、その相棒であるReact.useCallbackです。
useMemoはどのような問題を解決するのか
useMemoは、関数の出力を記憶するReactのフックです。
useMemoは関数と依存関係のリストの2つの引数を受け取ります。
useMemoは関数を呼び出し、その戻り値を返します。
その後、再び useMemo を呼び出すたびに、まず依存関係が変更されたかどうかをチェックします。
変更がなければ、キャッシュされた戻り値を返し、関数を呼び出しません。
変更されていれば、useMemo は提供された関数を再び呼び出し、このプロセスを繰り返します。
useEffectフックを思い出してください。
useMemoもuseEffectも依存関係のリストを受け入れます。
唯一の違いは、useEffectは副作用を目的としている(だからこの名前がついた)のに対し、
useMemoの関数は副作用のない純粋なものであると考えられていることです。
どんなときにuseMemoを使うのか
まず重要なのは、コードが useMemo に依存していてはいけないということです。
言い換えれば、useMemo の呼び出しを直接の関数呼び出しに置き換えても、アプリケーションの動作はパフォーマンスを除いて何も変わらないということです。
最も簡単な方法は、まず useMemo を使わずにコードを書き、必要に応じて追加していくことです。
useMemo を理解するために、どのような場合に使用するのか、次の例を見てみましょう。まず、useMemo を使わないこのコードを見てください。
この小さなアプリは、あなたの名前と数字を入力します。
そして、あなたに挨拶し、フィボナッチ数列から数字を表示します。
このアプリを実行すると、NameDisplayコンポーネントとFibDisplayの両方が、名前や数字を変更すると、再レンダリング(および高価な計算の実行)されることに気づくでしょう。
これは受け入れがたいことで、これを修正する方法があります。
まず、FibDisplayでuseMemoが使われていることに注目してください。
高価な計算を、長さが変化したときにのみ実行される関数に包んでいます。コンポーネントはまだ再レンダリングされますが、高価な計算は必要なとき以外は実行されません。
次に、NameDisplayコンポーネントがReact.memoでラップされていることに注目してください。
React.memoは、コンポーネント全体を記憶する方法です。これは、propsが変更されたときにのみ再レンダリングされるので、私たちの問題を完全に解決します。
でも、使いすぎは禁物
パフォーマンスの最適化は崇高な追求ですが、それを行うことによる影響や副作用を常に考慮する必要があります。
React.useMemoの場合はいくつかありまして、
オーバーヘッド
フック自体が新たに複雑なロジックを導入するため、解決するよりもパフォーマンスの問題が発生する可能性があります。本当に高価な計算でない限り、useMemo を適用しないでください。また、確信が持てない場合は、両方の方法でベンチマークを行い、十分な情報を得た上で判断してください。
保証なし
Reactのドキュメントにあるように、useMemoの内部メカニズムには絶対に依存してはいけません。言い換えれば、useMemoは依存関係が変化したときにのみ呼び出されることになっていますが、これは保証されていません。useMemo がすべてのレンダリング時にコールバックを呼び出す場合でも、アプリは完全に動作する必要があります(少し遅いかもしれませんが)。
React.memoを考えると、これらの懸念はすべて当てはまります。しかし、もう一つあります。React.memoは純粋なコンポーネントにのみ適用されるべきです。もう一つの問題は、Redux/Contextとhooksに関係しています。フックができる前は、Reduxのセレクタはprops経由でストア値を渡し、React.memoがそれをキャプチャしていました。しかし、useSelector/useContextを使用している場合、それらが変更されてもReact.memoはコンポーネントを再レンダリングしません。このような複雑な問題があるため、私はReact.memoを使用しないことをお勧めします。
終わりに、useCallback
useCallback は useMemo とほぼ同じですが、関数のためのものです。実際、useCallback(fn, deps)は useMemo(() => fn, deps)と同等である。useCallback は、依存関係が変更されない限り再宣言しないことで、多くのコールバック関数を使用するときにアプリをスピードアップすることになっている。ここでは、useCallback を使用した以前の例を紹介します。 お読みいただきありがとうございました。また、私の他の記事もチェックしてみてください。 [st-minihukidashi fontawesome="" fontsize="" fontweight="" bgcolor="#FFB74D" color="#fff" margin="0 0 20px 0" radius="" add_boxstyle=""]参考[/st-minihukidashi]