こんにちは、新人フロントエンドエンジニアのまりりんです!
普段はReact×TypeScriptを使うことが多く、無駄なレンダリングを抑える機能があることは知っているものの
曖昧な部分もあったので、今回はReactのmemo、useMemo、useCallback、lazyを実際のコードと共に試してみたいと思います!
バージョン情報
node:v20.11.1
react-dom@18.2.0
react-scripts@5.0.1
react@18.2.0
typescript@4.9.5
1. React.memoの活用
レンダリング結果が前回と同じであれば、コンポーネントを再レンダリングしないようにします。主に関数コンポーネントや純粋な関数のレンダリング結果をメモ化するために使用されます。
Nameコンポーネント
Addressコンポーネント
名前を入力すると、NameコンポーネントとAddressコンポーネント両方のconsole.logが出力されることが分かります。
今回は名前が入力されていますので、住所表示の再レンダリングは不要ですね。
一方で、住所を入力すると、Addressコンポーネントのみがconsole.logを出力していることが分かります。
これにより、不要なレンダリングが抑えられていることが確認できます。
2.React.useMemoの活用
値をキャッシュし、依存する値が変更されない限り、再計算を避けるために使用されます。主に計算結果やオブジェクトの生成など、再計算が不要な値をキャッシュするために使用されます。
まずは useMemoを使用しない例を見てみましょう。
テキストを入力するたび、console.logが実行されています。
では、useMemoを使ってみましょう。
テキストを変更しても、計算結果が変わらないのでconsole.logが実行されません。
ただし、useMemoの第2引数であるmaxNumber(画面上の「繰り返す回数」)が変わるとconsole.logが実行されることが分かります。
3. useCallbackの活用
イベントハンドラーは、適切にバインドされていないと不要な再レンダリングを引き起こす可能性があります。useCallbackフックを使用して、再レンダー間で関数定義をキャッシュすることができます。
最初はイマイチ利点が分からなかったのですが、React.memoと一緒に使うと再レンダリングを抑えられるようです!
React.memoのコードと似ていますが、微妙に構造を変えています。
Nameコンポーネント
Addressコンポーネント
Nameコンポーネントでは React.memoを設定していますが、住所を入力すると
NameコンポーネントとAddressコンポーネント両方のconsole.logが出力されることが分かります。
コード中のExample3コンポーネントにおけるhandleNameInput関数にuseCallbackを適用することで、再レンダリングの問題を解決します。
また、handleNameInput 関数内でnameステートを更新するために使用されているsetName関数をuseCallbackの依存リストに含めます。
Addressコンポーネントのみがconsole.logを出力していることが分かります。 これにより、不要なレンダリングが抑えられていることが確認できました!
4. React.lazyの活用
React.lazyは、Reactコンポーネントを遅延ロード(動的にロード)するためのReactの機能です。通常、Reactアプリケーションでは、すべてのコンポーネントが最初からロードされますが、 React.lazyを使用すると、コンポーネントが必要になるまでロードされません。これにより、初期ロード時間を短縮し、アプリケーションのパフォーマンスを向上させることができます。
React.lazyを使用するには、動的にロードされるコンポーネントをimportする必要があります。
遅延ロード用のコンポーネント
React.lazyを使うことで、AsyncComponentが必要になるまでロードされず、必要になった時点で非同期的に読み込みます。この方法を使用すると、初期ロード時間を減らすことができます。
React.lazyを使用する際には、Suspenseコンポーネントと一緒に使用することが推奨されます。
Suspenseコンポーネントは、遅延ロードされたコンポーネントがロードされるまでの間に表示される内容です。
React.lazyとSuspenseを組み合わせることで、Reactアプリケーションのパフォーマンスを最適化することができます。
さいごに
今後リリースされるReact 19では、React Compilerによって最適化されるそうなのでmemo、useMemo、useCallbackは手動で使う機会が減るかもしれませんが、知っておいて損は無いと思いました。
実際にコードを書いてみて、ブログを書く前より理解が深まりました!
また、React.lazyは今回初めて知った機能でした。知らない機能はまだまだあるので、より良いコードを書けるように頑張ります!