ReactのEffectListの簡単な分析

ReactのEffectListの簡単な分析

React では、ノード操作、ライフサイクル メソッド、および Effect メソッドを実行するために EffectList がトラバースされます。EffectList はクリスマス ツリーにぶら下がっているカラフルなライトに例えることができ、このクリスマス ツリーは Fiber ツリーです。

EffectList はなぜ存在するのでしょうか?たとえば、ファイバー ツリーには、 componentDidMountメソッドを実行する必要があるファイバー ノードがいくつかあります。ファイバー ツリーを構築してから再度走査して、 componentDidMountメソッドを実行する必要があるファイバー ノードを見つけるのは、非常に非効率的です。

EffectList はこの問題を解決します。ファイバー ツリーの構築中に、ファイバー ノードのflagsフィールドがNoFlags (副作用を実行する必要があることを示す) でない場合は、ファイバー ノードが EffectList に追加されます。ファイバー ツリーが構築された後、ファイバー ノードによって連結された色付きのライトも構築されるため、色付きのライトをトラバースするだけで済みます。

EffectList コレクション

EffectList は一方向のリンク リストです。firstEffect firstEffectリンク リストの最初の Fiber ノードを表し、 lastEffectリンク リストの最後の Fiber ノードを表します。

ファイバー ツリーの構築は深さ優先です。つまり、子ファイバー ノードが最初に下向きに構築され、子ノードが構築された後に親ファイバー ノードが上向きに構築されるため、子ファイバー ノードは常に EffectList の先頭になります。

Fiber ノードの構築を完了する操作は、 completeUnitOfWorkメソッドで実行されます。このメソッドでは、ノードが完了するだけでなく、 flags付きの Fiber ノードが EffectList に追加されます。

簡略化されたコードは次のとおりです。

関数 completeUnitOfWork(unitOfWork: Fiber): void {
 完了した作業 = unitOfWork とします。
 する {
  現在の作業を完了します。
  const returnFiber = 完了した作業.return;
  
  次は、completeWork を現在の作業、completedWork、subtreeRenderLanes に格納します。

  // エフェクトリストの構築 if (
   returnFiber !== null &&
   (returnFiber.flags & 不完全) === NoFlags
  ){
   // レイヤーごとにコピーします if (returnFiber.firstEffect === null) {
    戻り値:
   }
   完了した作業の最後の効果が null ではない場合
    // これは、現在のノードが兄弟ノードであり、子ノードに効果があり、returnFiber.lastEffect に値が割り当てられていることを意味します if (returnFiber.lastEffect !== null) {
     // 兄弟ノードを接続する効果
     戻り値:
    }
    戻り値:
   }
   
   const flags = 完了した作業.flags;
   
   // このファイバーノードには効果があります
   if (フラグ > 実行された作業) {
    // 現在のノードにはエフェクトリストに接続されたエフェクトがあります
    returnFiber.lastEffect !== null の場合 {
     完了した作業を返します。
    } それ以外 {
     // returnFiber に firstEffect がない場合、効果を持つノードに初めて遭遇したときです。 returnFiber.firstEffect = CompletedWork;
    }
    完了した作業を返します。
   }
  }

  // 兄弟要素を走査し、親に戻ります。const siblingFiber = completeWork.sibling;
  兄弟ファイバーが null の場合
   作業進行中 = 兄弟ファイバー;
   戻る;
  }
  完了した作業 = returnFiber;
  進行中 = 完了した作業;
 } while (completedWork !== null);
}

EffectList は実際にはバブルのように動作し、 flagsが付いた最初のノードから始めて、上位のレイヤーにレイヤーごとにデータを収集します。各レイヤーの新しいノードはそれぞれ、前のノードのfirstEffectlastEffectを自分自身にコピーし、上位のノードに再度コピーを提供します。

次の構造のように、各divflagsがある場合。

<div id="1">
 <div id="4"/>
 <div id="2">
  <div id="3"/>
 </div>
</div>

最終的なEffectListは

最初の効果 => div4
最後の効果 => div1

Fiber ツリーは深さ優先で構築されるため、すべてのdiv4最初にcompleteWorkを完了し、 firstEffectを構築します。

EffectList のトラバーサルはfirstEffectから始まり、各ノードのnextEffectを通じて次のノードを見つけます。

最初の効果 => div4
div4.nextEffect => div3
div3.nextEffect => div2
div2.nextEffect => div1

最初のレンダリング時のEffectList

React では、最初のマウントに対してパフォーマンスの最適化が行われ、Fiber ノードのflagsplacementが含まれなくなり、対応する DOM ノードはトラバースされて DOM ツリーに追加されませんが、DOM ノードが作成されるときに DOM ツリーに追加されます。rootFiber ノードのFiberRootNodeflagsにのみplacementが含まれます。

EffectList にはrootノードが含まれていないため、 placement正しく実行され、DOM ツリーがページに表示されるようにするには、EffectList にrootノードを追加する必要があります。

 最初の効果をさせる;
 // ルートノードfinishedWorkも接続します if (finishedWork.flags > PerformedWork) {
  終了した作業の最後の効果が null の場合
   終了した作業.lastEffect.nextEffect = 終了した作業;
   firstEffect = 完成した作業。firstEffect;
  } それ以外 {
   最初の効果 = 完成した作業;
  }
 } それ以外 {
  // ルートノードは効果がありません。
  firstEffect = 完成した作業。firstEffect;
 }

EffectList のトラバーサル

EffectList は主に、レイアウト フェーズのライフ サイクル メソッドと DOM 操作の実行に使用されます。

// getSnapshotBeforeUpdate を処理し、useEffect をスケジュールする
次のエフェクト = 最初のエフェクト;
する {
 コミット前にミューテーション効果();
} while (nextEffect !== null);
//DOM 操作 nextEffect = firstEffect;
する {
 commitMutationEffects(ルート、renderPriorityLevel);
} while (nextEffect !== null);
// ライフサイクルメソッドの実行 nextEffect = firstEffect;
する {
 commitLayoutEffects(ルート、レーン);
} while (nextEffect !== null);

レイアウト ステージのこれらの 3 つのメソッドでは、 nextEffectがトラバースされ、実行されるたびにfirstEffectが再度ポイントされます。レイアウト段階での具体的な操作については詳しく説明しません。

要約する

EffectList はグローバル変数ではありません。ファイバー ツリーの作成中に、 effectを持つファイバー ノードがレイヤーごとに収集されます。最終的なrootノードは、 effectを持つすべてのファイバー ノードを収集します。 effectノードを含むこのリンク リストを EffectList と呼びます。

コレクション プロセスは深さ優先であるため、子が最初にコレクションされ、トラバーサル中に子が最初に操作されます。そのため、面接官が子と親のライフ サイクルまたはuseEffectどちらが最初に実行されるかを尋ねた場合、子の操作が最初に実行されることが明確にわかります。

上記はReactのEffectListの詳細についての簡単な分析です。ReactのEffectListの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • フックを使用して React コンポーネントを書くときに注意すべき 5 つの点
  • React+Ant Design開発環境をセットアップするための実装手順
  • ViteでReactプロジェクトを構築する方法
  • 入力ボックスの値を取得する方法のReactの例
  • Reactはラジオコンポーネントのサンプルコードを実装します
  • React Router で履歴リダイレクトを使用する方法
  • React Contextの理解と応用についてお話ししましょう
  • Reactフック入門チュートリアル
  • React と Threejs を使用して VR パノラマ プロジェクトを作成する詳細なプロセス

<<:  マルチコア CPU を使用して Linux コマンドを高速化する方法 (GNU Parallel)

>>:  Django+mysql の設定と簡単な操作データベースのサンプルコード

推薦する

JSにおけるデータ型の正しい判定方法の例

目次序文typeof は型を正しく判別できますか? instanceof は型を正しく判別できますか...

MySQLはtruncateコマンドを使用してデータベース内のすべてのテーブルを素早くクリアします

1. まずSELECT文を実行して、すべての切り捨て文を生成します。ステートメント形式: selec...

MySQL データベースの高度なクエリとマルチテーブルクエリ

MySQL マルチテーブルクエリワークシートを追加する -- ユーザーテーブル (ユーザー) テーブ...

フロントエンドエンジニアが作ったクールなインタラクティブウェブサイトを推薦します

ウェブサイトリンク: http://strml.net/サミュエル・リード著ヒント: 昨日、Mome...

divは、自動入力スタイルをブロックする入力ボックスとして入力を使用せずにコンテンツを入力できます。

今日、私は公開用の動的なウィンドウ スタイルを設計しましたが、マウスで入力をクリックしたときにブラウ...

なぜCSSをヘッドタグに配置する必要があるのか

考えてみてください。なぜcss 、 javascriptのようにbodyタグの末尾ではなく、 hea...

MySQLのINサブクエリによってインデックスが使用できなくなる問題を解決する

今日は、MySQL IN サブクエリの最適化に関するケーススタディを見ました。最初は少し懐疑的でした...

MySQL遅延スレーブを導入するメリットのまとめ

序文MySQL のマスター/スレーブ レプリケーション関係は、厳密には「同期」または「マスター/スレ...

CSS グラデーション効果の概要 (線形グラデーションと放射状グラデーション)

線形グラデーション 背景画像: linear-gradient(方向、開始色、中間色1、中間色2、....

ノードを使用して静的ファイルキャッシュを実装する方法

目次キャッシュキャッシュ位置の分類キャッシュ設定ヘッダーNodeは静的ファイルキャッシュを実装する強...

TOM.COMのホームページリニューアルの経験

<br />何の警告もなく、cnBeta で TOM.COM の Web サイトが再設計...

Linuxのpasswdコマンドの使用

1. コマンドの紹介passwd コマンドは、ユーザー パスワード、アカウント ロック、パスワードの...

意外と知らないLinuxのSSHコマンドの使い方7選を徹底解説

システム管理者は複数のサーバーを同時に管理する場合があり、これらのサーバーは異なる場所に配置されてい...

HTML インライン要素と HTML ブロックレベル要素の概要と違い

ブロックレベル要素の機能: • 常に新しい行から始まり、それ自体で 1 行を占め、後続の要素も新しい...

WeChatアプレットコンポーネントライフサイクルの落とし穴の記録

通常、コンポーネントのライフサイクルは、ビジネス ロジックが始まる場所です。ビジネスシナリオが複雑で...