Reactが「再レンダリング」と言うとき、それは3つのことを意味している
setStateを呼び出すとき、Reactは単にDOMを更新するだけではありません。Reactは3つの異なるフェーズを順番に実行します。多くの開発者がこれらのフェーズを混同してしまいます。その違いを理解することは、パフォーマンスの問題を解決するのに役立ちます。
3つのフェーズ:
• Render: Reactがコンポーネント関数を呼び出します。 • Reconcile: Reactが新しい出力と古い出力を比較します。 • Commit: Reactが変更をDOMに適用します。
- Renderフェーズ
Reactは関数を実行します。その際、現在のpropsを使用します。関数はJSXを返します。このJSXは単なるJavaScriptオブジェクトのリストです。人々はこれをvirtual DOMと呼びます。これは実際のDOMではありません。UIがどのようになるべきかを示す記述です。この段階では、画面にはまだ何も表示されません。このフェーズは純粋な数学とロジックのプロセスです。
- Reconcileフェーズ
Reactは古いツリーと新しいツリーを保持します。そして、それらの間の違いを探します。要素のタイプが変わった場合、Reactはツリー全体を置き換えます。propsだけが変わった場合は、Reactはそれらを更新します。ここで重要になるのがkeyです。keyは、Reactがリスト内のアイテムを位置ではなく識別子によって一致させるのに役立ちます。このフェーズでは、DOMを更新するために必要な最小限の手順のリストが作成されます。
- Commitフェーズ
Reactは変更のリストを受け取り、実際のDOMに触れます。新しいノードを作成し、古いノードを削除します。ユーザーが画面上の変化を目にするのはこの時です。この後、ブラウザが画面を描画(paint)します。そして、useEffectが実行されます。
よくある誤解:
• 再レンダリングが常にDOMを変更するわけではありません。出力が同じであれば、Reactはcommitフェーズで何も行いません。
• React.memoは関数の呼び出しをスキップしますが、DOMの更新をスキップするわけではありません。
• propsが再レンダリングをトリガーするわけではありません。親コンポーネントの再レンダリングが子コンポーネントをトリガーします。propsの変化は、単なる結果に過ぎません。
パフォーマンスを改善する方法:
関数が遅い場合は、Renderの問題があります。重い処理を関数の外に出すか、メモ化(memoization)を使用してください。
Reactが巨大なリストを再構築している場合は、Reconcileの問題があります。keyを確認してください。
DOMの更新が多すぎる場合は、Commitの問題があります。仮想化(virtualization)を使用するか、構造を変更してください。
React 19とReact Compilerが、現在これらの作業の多くを自動で行ってくれます。しかし、これらのフェーズを知っておくことは、より良いデバッグに役立ちます。
