React の内部構造の概要
React の内部構造を 4 つのフェーズに分けて概説します。
React Internals Overview
3.1 トリガー
すべての作業がここから始まるため「トリガー」と名付けました。初期マウントであっても state hook による再レンダーであっても、このフェーズではどの部分をレンダーすべきか(scheduleUpdateOnFiber()
)、そしてどのように行うべきかを React ランタイムに伝えます。
このフェーズは「タスクの作成」と考えることができます。ensureRootIsScheduled()
がそのようなタスクを作成する最後のステップであり、scheduleCallback()
を通じてタスクが Scheduler に送信されます。
関連トピック:
3.2 スケジューリング
これは React Scheduler で、基本的に優先度キューであり、優先度に応じてタスクを処理します。レンダリングやエフェクトの実行などのタスクをスケジュールするために、ランタイムコードでscheduleCallback()
が呼び出されます。Scheduler 内部のworkLoop()
が実際にタスクを実行する方法です。
Scheduler の詳細は以下を参照:
3.3 レンダー
レンダーはスケジュールされたタスク(performConcurrentWorkOnRoot()
)であり、新しい Fiber Tree の計算とホスト DOM に適用する必要のある更新の特定を行います。
Fiber Tree の詳細を知る必要はありません。これは基本的に、アプリの現在の状態を表す内部的なツリー構造です。以前は Virtual DOM と呼ばれていましたが、現在は DOM 以外にも使用され、React チームはもはや Virtual DOM とは呼びません。
performConcurrentWorkOnRoot()
はトリガーフェーズで作成され、Scheduler で優先度付けされた後、ここで実際に実行されます。Fiber Tree を巡回し、再レンダーの必要性をチェックし、ホスト DOM に必要な更新を導出する小さな作業員がいるかのように考えてください。
コンカレントモードでは、「レンダー」フェーズが中断されて再開される可能性があるため、非常に複雑なステップとなります。
詳細は以下を参照:
- React 内部で Fiber ツリーをどのように巡回するか?
- Reconciliation における React の bailout はどのように機能するか?
- React 内部で'key'はどのように機能するか?リストの差分検出
- React ソースコードにおける Lanes とは?
3.4 コミット
新しい Fiber Tree が構築され、最小限の更新が導出された後、ホスト DOM への更新を「コミット」する時が来ます。
もちろん DOM 操作だけではありません(commitMutationEffects()
)。例えば、すべての種類のエフェクトがここで処理されます(flushPassiveEffects()
、commitLayoutEffects()
)。
関連トピック:
- useLayoutEffect()の内部動作
- React 内部で useEffect()はどのように動作するか?
- React 内部で useTransition()はどのように動作するか?
- エフェクトフックのライフサイクル
4. まとめ
React Internals Deep Diveの最初のエピソードは以上です。デバッガを設定するだけで、どれだけ多くの情報が得られるかわかります。
一度に 1 つのパズルを解くように取り組めば、毎日 React をより深く理解できるようになります。行き詰まったら、Discord サーバーで連絡してください。
この記事がお役に立てば幸いです。