Obake Engineer Blog

Reactのレンダリングプロセス

React

2021/01/10

Reactのレンダリングプロセスには2段階のステージがある。
①Render ステージ
②Commit ステージ

①のRenderステージは、仮想DOMの構築から差分検出処理(リコンシリエーション)までを含む。 ②のCommitステージは、検出した差分を実DOMに反映する段階である。

React のライフサイクルメソッド図

①Renderステージ

このステージで行われることは、

  1. 仮想DOMの構築
  2. 差分検出処理

である。
RenderステージでレンダリングされているDOMについては、React Developer ToolsのHighlight updates when components render機能で可視化することができる。

①-1 仮想DOMの構築

初回レンダリングではマウントが起こり、DOMを0から構築する。マウント後はpropsやstateの変更が起きたコンポーネント、及びその子コンポーネントのみ再レンダリングされる。(createReactElement()が実行される。)

ここでいうレンダリングとは、関数コンポーネントの本体(あるいはクラスコンポーネントのrender())が呼ばれることを指す。

この段階の無駄な再レンダリングを防ぐ方法を以下に示す。

関数コンポーネントの場合

  • React.memo
jsx
const MyComponent = React.memo(function MyComponent(props) {
  /* render using props */
});

もしあるコンポーネントが同じ props を与えられたときに同じ結果をレンダーするなら、React はコンポーネントのレンダーをスキップし、最後のレンダー結果を再利用します。

React.memoを使用することで、受け取ったpropsが等価の場合にそのコンポーネントのレンダリングをスキップすることができる。

  • useCallback
jsx
const memoizedCallback = useCallback(
  () => {doSomething(a, b);},
  [a, b],
);

React.memoと併用することで、コンポーネントの不要な再レンダリングをスキップできる。あるコンポーネントにアロー関数をpropsとして渡している場合は、renderのたびに新しい関数を生成するため、React.memoが意味をなさなくなる。useCallbackはアロー関数の再生成を防ぐことができる。

クラスコンポーネントの場合

  • ShouldComponentUpdate()

    • props(とstate)の変更を検知し、変更が無いとみなされれば、そのコンポーネントのレンダリングをスキップすることができる。
    • デフォルトではShouldComponentUpdate()は常にtrueを返すため、常に再レンダリングが起こるようになっている。
  • PureComponent

    • propsとstateをshallow compareし、変更が無いとみなされれば、そのコンポーネントのレンダリングをスキップすることができる。
    • ShouldComponentUpdateの代用となる。
    • [React] Component と PureComponentの違い - Qiita

①-2 差分検出処理

①-1で構築した仮想DOMと、実DOMの差分を検出する。
このときkey値が同じDOMは差分が無いとみなすことができ、後の実DOM構築の処理を少なくすることができる。
詳しくはReact公式の差分検出処理を参照。

②Commitステージ

①-2で検出した差分を実DOMに反映する段階である。 このとき描画されるDOMは、Chrome devtoolsのrendering > paintflashingで確認することができる。

参考

  • Reactのレンダリングに関する完全ガイド - Qiita
  • React.memo / useCallback / useMemo の使い方、使い所を理解してパフォーマンス最適化をする - Qiita
  • リアルな DOM はなぜ遅いのか
  • React に優しい僕でありたい - Qiita
  • React製のSPAのパフォーマンスチューニング実例

/post-10

Reactのレンダリングプロセス

Related Posts

  • TypeScript環境でEmotionのスタイル指定に任意のpropsを渡す方法
  • Reactのレンダリングメモ
  • 「create-react-app」+ 「TypeScript」環境で絶対パスのaliasを指定する

Search

Recent Posts

  • Apollo Clientでリクエストヘッダーに認証トークンを付与する方法
  • 【Zsh】コマンド履歴にエラーの履歴を残さない設定
  • 【Laravel】PHPUnit実行時に開発用DBを初期化してしまわないために
  • TypeScript環境でEmotionのスタイル指定に任意のpropsを渡す方法
  • Reactのレンダリングメモ

All Tags

JavaScript (7)
React (4)
GatsbyJS (3)
TypeScript (3)
Zsh (2)
Webpack (2)
Git (1)
CSS (1)
Dotenv (1)
Redux (1)
Emotion (1)
Laravel (1)
PHP (1)
GraphQL (1)
Apollo (1)
obake
Obake Engineer Blog

の検索結果: 0件中 0件表示