🐣 【日報】React実践の教科書 P165〜174
作成日: 2021/12/21
1

今日やったこと

  • 「モダンJavaScriptの基本から始める React実践の教科書」 P165〜174
    • 6-2 レンダリング最適化1(memo)
    • 6-3 レンダリング最適化2(useCallback)
    • 6-4 変数のmemo化(useMemo)

学習メモ

React.memo

  • コンポーネント、変数、関数などの再レンダリング時の制御をするためにメモ化を行う
    • 前回の処理結果を保持しておくことで処理を高速化する技術
    • 今回の例ではコンポーネントのメモ化を行うことで、親のコンポーネントが再レンダリングしても子のコンポーネントの再レンダリングを防ぐことができる
  • メモ化の機能はReactが提供してくれており、Reactの中にあるmemoを使用する
    • memoはコンポーネント関数全体をカッコで囲むだけで使用することができる
const Component = memo(() => {});

メモ化前:

import { useState } from "react";
// …省略
export const App = () => {
// …省略
};

メモ化後:

import { useState, memo } from "react";
// …省略
export const App = memo(() => {
// …省略
});

メモ化したことで、ボタンを押したときにAppコンポーネントのみがレンダリングされるようになった
スクリーンショット 2021-12-21 22.39.16.png

React.useCallBack

事前準備として、 Child1 の中に「押すとカウントアップ中の数値を0に戻すリセットボタン」を配置
スクリーンショット 2021-12-21 22.50.37.png

最適化したはずの再レンダリングを再度確認すると、
カウントアップの度にChild1が再レンダリングされるようになっている
スクリーンショット 2021-12-21 22.50.52.png

  • 関数をPropsに渡すときにコンポーネントをメモ化していても再レンダリングされてしまう原因は関数の再生成

  • 再レンダリングで以下のコードが実行される度に新しい関数が再生成されている

  const onClickReset = () => {
    setNum(0);
  };
  • そのため、関数をPropsとして受け取っているChild1は、Propsが変化したと判定してカウントアップの度に再レンダリングしている。この事象を回避するために関数のメモ化を行う
  • 関数のメモ化についてはReactが提供してくれているuseCallbackを使用する
    • 第1引数に関数、第2引数にuseEffectと同じく依存配列をとる

useCallbackの例:

const onClickButton = useCallback(() => {
	console.log("ボタンが押されました");
}, []);

依存配列を空にすると最初に作成されたものが使い回されるようになる
スクリーンショット 2021-12-21 23.29.45.png

React.useMemo

  • 変数のメモ化として useMemo というものがReactに用意されている
  • useEffectやuseCallbackとほとんど同じ構文だが、第1引数の関数で変数に設定する値の返却、第2引数に依存配列をとる

useMemoの構文:

const sum = useMemo(() => {
	return 1 + 3;
}, []);
  • 上記の場合では、第2引数が空配列になっているので初回読み込み時のみ「1+3」という計算を実行し、それ以降再レンダリングされたときは最初の値を使い回すことができるようになる
  • もちろん、依存配列に変数を設定しておくことでその値が変わった時のみ変数を再設定することができる
  • 変数設定のロジックが複雑だったり、膨大な数のループが実行される場合などに使用することで変数設定による負荷を下げることができる
  • 依存配列に設定されている値を見ることでその変数を設定するのに影響を与えている外部の値を明示的に示すことができるため、可読性の向上も期待できる

所感

再レンダリングについてのチャプターが終わりました。
後々困ることのないよう、小規模のアプリを作るときでも、最適化をしながら進めていくようにしたいです。