レンダリングフェーズとDOMコミット
JSXの評価からReconciliationを経てブラウザーの描画段階に至るReactのレンダリングサイクルを追跡します
「レンダリングフェーズとDOMコミット」はCoddyKit上の無料React Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
Reactのワークサイクルの概要
Reactのワークサイクルには、レンダーフェーズとコミットフェーズという2つの主要なフェーズがあります。レンダーフェーズでは、Reactがコンポーネント関数を呼び出し、UIの仮想表現(Fiberツリー)を構築します。コミットフェーズでは、ReactがFiberツリーの変更を実際のDOMに適用します。
レンダーフェーズは中断可能
React 18のConcurrent Modeでは、レンダーフェーズを一時停止、中断、再開できます。Reactは何もコミットしないまま、コンポーネント関数を複数回呼び出すことがあります。そのため、コンポーネント関数は純粋でなければなりません。関数は表示上の1回の更新に対して複数回実行される可能性があるため、副作用を持たせることはできません。
コミットフェーズは常に同期的に実行される
レンダーフェーズとは異なり、コミットフェーズは常に同期的に実行され、最後まで完了します。ReactはDOMの変更をコミットしている間、中断されることがありません。これにより、DOMが部分的に更新された状態のままになることを防げます。ユーザーには、各コミットの後に常に整合性のあるUI全体が表示されます。
コミットの3つのサブフェーズ
コミットフェーズには、mutation前、mutation、layoutという3つのサブフェーズがあります。mutation前では、クラスコンポーネントのgetSnapshotBeforeUpdateが変更前のDOM値を読み取ります。mutationでは、ReactがDOMノードを挿入、更新、削除します。layoutでは同期的なエフェクトが実行され、具体的にはuseLayoutEffectとクラスコンポーネントのcomponentDidMount/componentDidUpdateが実行されます。
パッシブエフェクト:useEffect
useEffectはパッシブエフェクトです。つまり、コミットフェーズ中には実行されません。コミットフェーズが完了してブラウザーがペイントした後、Reactはパッシブエフェクトを非同期でスケジュールします。これらは、ブラウザーが更新されたDOMを画面に描画する機会を得た後に実行されます。
ブラウザーのペイントタイミング
ブラウザーは、useLayoutEffectが実行されるlayoutフェーズと、useEffectが実行されるパッシブエフェクトフェーズの間にペイントします。ここが重要なタイミングの違いです。useLayoutEffectはペイント前に実行され、useEffectはペイント後に実行されます。表示結果を変更するエフェクトでは、この違いが大きく影響します。
useEffectが視覚的な二重更新を引き起こす理由
useEffectでDOMを読み取り、状態を更新すると(たとえば要素のサイズを測定してサイズの状態を設定すると)、Reactは再度レンダーしてコミットします。ブラウザーは、最初のサイズで1回、修正後のサイズでもう1回、合計2回ペイントします。そのためユーザーには、修正後のサイズが表示される前に、誤ったサイズが一瞬表示されることがあります。
Fiberツリー
Reactは内部的に、コンポーネントのインスタンスごとに1つの「fiber」ノードからなるツリーを構築します。各fiberには、コンポーネントのstate、エフェクト、出力が保持されます。レンダーフェーズでは、Reactは作業中のFiberツリーを新しく作成します。コミットフェーズでは、作業中のツリーがcurrentツリーになり、古いツリーは再利用されます。
Strict Modeでの二重呼び出し
React Strict Modeでは、副作用を見つけやすくするため、開発時にコンポーネント関数とエフェクトを意図的に2回呼び出します。useLayoutEffectとuseEffectは、どちらもマウント、アンマウント、再マウントされます。この二重呼び出しは本番環境では発生しません。エフェクトが適切にクリーンアップされていない場合にバグを表面化させるための仕組みです。
コンポーネント関数が純粋でなければならない理由
レンダーフェーズは中断された後に再実行される可能性があるため、コンポーネント関数は副作用なしで、同じ入力に対して常に同じ出力を生成しなければなりません。関数本体で(エフェクト内ではなく)ミューテーション、サブスクリプション、API呼び出しを行うと、Concurrent Modeでは想定より多く実行され、バグの原因になります。
レンダー中とエフェクト内でのDOM読み取り
コンポーネント関数の本体でDOMプロパティを直接読み取ってはいけません。サーバーレンダリングではDOMがまだ存在しない可能性があり、再レンダー時には古い状態になっている可能性があります。DOMが最新の状態であることが保証されるuseLayoutEffect(ペイント前の読み取り)またはuseEffect(ペイント後の読み取り)の中で、必ずDOMを読み取ってください。
Reactのコミットフェーズのサブフェーズ
ReactのコミットフェーズのどのサブフェーズでuseLayoutEffectが実行されますか?
レッスンのまとめ:レンダリングフェーズとDOMコミット
ReactのレンダーフェーズはFiberツリーを構築し、中断される可能性があります。一方、コミットフェーズはDOMの変更を適用し、常に同期的に実行されます。コミットには、ミューテーション前、ミューテーション、レイアウトという3つのサブフェーズがあります。useLayoutEffectはペイント前のレイアウトフェーズで実行されます。useEffectはペイント後にパッシブエフェクトとして実行されます。
よくある質問
「レンダリングフェーズとDOMコミット」レッスンは無料ですか?
はい。「レンダリングフェーズとDOMコミット」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「レンダリングフェーズとDOMコミット」で何を学びますか?
JSXの評価からReconciliationを経てブラウザーの描画段階に至るReactのレンダリングサイクルを追跡します ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「レンダリングフェーズとDOMコミット」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- レンダリングフェーズとDOMコミット
- useLayoutEffectとuseEffectの実行タイミング
- useLayoutEffectによるDOM要素の測定
- レイアウトスラッシングと視覚的なちらつきの回避