【React】無駄な再レンダリングをさせない、レンダリングの最適化

Reactで開発をする上では、レンダリングがどのような条件でされるかを把握しておき、動作の軽いアプリに仕上げる必要があります。

そのために必要な知識として、再レンダリングについてまとめました。

再レンダリングが起きるタイミング

まずは、再レンダリングがいつ起きるのかを知りましょう!

  • コンポーネントのstateが更新されたとき
  • 親コンポーネントが受け取るpropsが変更されとき
  • 再レンダリングされたコンポーネントの配下の子コンポーネント

最適化の方法

再レンダリングが必要以上に起きるのを防ぐための方法として、コンポーネントのmemo化、関数のmemo化といった方法があります。

memo機能を使う

memo

memoでできること

親コンポーネントが更新されても子コンポーネントに変更が無い限り、子コンポーネントは再レンダリングされないようにできる。

記述方法

子コンポーネントで以下の処理を行う。

  • memoをimport
  • memoでコンポーネントを囲う

これで子コンポーネントは親コンポーネントの影響を受けないことになりました。

import { memo } from "react";

export const ChildArea = memo((props) => {
  const { open } = props;
  return (
    <>
      <div>
        <p>子コンポーネント</p>
      </div>
    </>
  );
});

useCallback

上記のmemoでは再レンダリングを防げない場合があります。

それは、memo化した中にアロー関数が使用されている場合です。

関数は、propsとしては毎回違う関数という判断となるため、子コンポーネントが毎回更新されてしまうという問題が起きます。

これを解決するために、処理が変わらない場合は同じものを使い回すという処理をしてあげる必要があり、useCallbackというものを使います。

memoと同様に、useCallbackをreactからimportします。

import { useState, useCallback } from "react";

アロー関数をuseCallbackで囲い、第二引数には、監視する値を指定します。

この値は、ここの値が変わったときに関数を実行するよ!というもの。

const onClickClose = () => setOpen(false);

↓

const onClickClose = useCallback(() => setOpen(false), []);

このようにuseCallbackを使用することで、onClickCloseが他のコンポーネントで使用される際に、再生成がされないようにすることができる。

このuseCallback、useEffectとなんか似ていませんか?

そこで、何が違うのか整理しました。

useCallbackとuseEffectの違い

処理を実行する値の監視(第二引数)はどちらも同じように設定できるので、同じ形をしていますが、そもそもの役割が全く違います。

useCallback・・・キャッシュした結果を返すことで、再レンダリングが起きないようにできる。

useEffect・・・監視した値は、返り値の変更有無に関わらず、結果を返す。

つまり、同じ結果を返すにも関わらず、何回も同じ処理をして、無駄に働いているのを、useMemoとuseCallbackを使って、必要なときだけとし、エコにしているってことですね!

以上、Reactにおける再レンダリングの必要な知識についてでした!

コメント