Simple analysis of EffectList in React

Simple analysis of EffectList in React

In React, EffectList is traversed to perform node operations, lifecycle methods, and Effect methods. EffectList can be compared to the colorful lights hanging on a Christmas tree, and this Christmas tree is the Fiber tree.

Why does EffectList exist? For example, there are some Fiber nodes in a Fiber tree that need to execute the componentDidMount method. If the Fiber tree is built and then traversed again to find the Fiber nodes that need to execute componentDidMount method, it is very inefficient.

EffectList solves this problem. During the construction of the Fiber tree, whenever the flags field of a Fiber node is not NoFlags (indicating that side effects need to be performed), the Fiber node is added to the EffectList. After the Fiber tree is built, the colored lights strung together by the Fiber nodes are also built, so you only need to traverse the colored lights.

EffectList Collection

EffectList is a one-way linked list. firstEffect represents the first Fiber node in the linked list, lastEffect represents the last Fiber node in the linked list.

The construction of the Fiber tree is depth-first, that is, the child Fiber nodes are built downwards first, and after the child nodes are built, the parent Fiber nodes are built upwards, so the child Fiber nodes are always in front in the EffectList.

The operation of completing the construction of the Fiber node is executed in the completeUnitOfWork method. In this method, not only the node is completed, but also the Fiber node with flags is added to the EffectList.

The simplified code is as follows.

function completeUnitOfWork(unitOfWork: Fiber): void {
 let completedWork = unitOfWork;
 do {
  const current = completedWork.alternate;
  const returnFiber = completedWork.return;
  
  let next = completeWork(current, completedWork, subtreeRenderLanes);

  // effect list construction if (
   returnFiber !== null &&
   (returnFiber.flags & Incomplete) === NoFlags
  ) {
   // Copy layer by layer if (returnFiber.firstEffect === null) {
    returnFiber.firstEffect = completedWork.firstEffect;
   }
   if (completedWork.lastEffect !== null) {
    // This means that the current node is a sibling node, the child node has an effect, and returnFiber.lastEffect has been assigned a value if (returnFiber.lastEffect !== null) {
     // Effect of connecting sibling nodes
     returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
    }
    returnFiber.lastEffect = completedWork.lastEffect;
   }
   
   const flags = completedWork.flags;
   
   // This fiber node has an effect
   if (flags > PerformedWork) {
    // The current node has an effect connected to the effect list
    if (returnFiber.lastEffect !== null) {
     returnFiber.lastEffect.nextEffect = completedWork;
    } else {
     // The case where returnFiber does not have firstEffect is the first time it encounters a node with effect returnFiber.firstEffect = completedWork;
    }
    returnFiber.lastEffect = completedWork;
   }
  }

  // Traverse the sibling elements and return to the parent const siblingFiber = completedWork.sibling;
  if (siblingFiber !== null) {
   workInProgress = siblingFiber;
   return;
  }
  completedWork = returnFiber;
  workInProgress = completedWork;
 } while (completedWork !== null);
}

EffectList actually works like a bubble, collecting data layer by layer to the upper layer, starting from the first node with flags . Each new node in each layer will copy firstEffect and lastEffect of the previous node to itself, and then provide the upper node with a copy again.

As in the following structure, if each div has flags .

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

The final EffectList is

firstEffect => div4
lastEffect => div1

Because the Fiber tree is constructed depth-first, all div4 completes completeWork first and builds firstEffect .

EffectList traversal starts from firstEffect and finds the next node through nextEffect of each node.

firstEffect => div4
div4.nextEffect => div3
div3.nextEffect => div2
div2.nextEffect => div1

EffectList at the first render

In React, there is a performance optimization for the first Mount, in which the Fiber node's flags will not include placement , and the corresponding DOM node will not be traversed and added to the DOM tree, but will be added to the DOM tree when the DOM node is created. Only the rootFiber node FiberRootNode 's flags will include placement .

EffectList does not include root node, so you need to add root node to EffectList so that placement can be executed correctly and the DOM tree can be presented on the page.

 let firstEffect;
 // Connect the root node finishedWork as well if (finishedWork.flags > PerformedWork) {
  if (finishedWork.lastEffect !== null) {
   finishedWork.lastEffect.nextEffect = finishedWork;
   firstEffect = finishedWork.firstEffect;
  } else {
   firstEffect = finishedWork;
  }
 } else {
  // The root node has no effect.
  firstEffect = finishedWork.firstEffect;
 }

Traversal of EffectList

EffectList is mainly used for the execution of Layout phase life cycle methods and DOM operations.

// Process getSnapshotBeforeUpdate and schedule useEffect
nextEffect = firstEffect;
do {
 commitBeforeMutationEffects();
} while (nextEffect !== null);
//DOM operation nextEffect = firstEffect;
do {
 commitMutationEffects(root, renderPriorityLevel);
} while (nextEffect !== null);
// Execution of life cycle methods nextEffect = firstEffect;
do {
 commitLayoutEffects(root, lanes);
} while (nextEffect !== null);

In these three methods in the Layout stage, nextEffect will be traversed, and each time it is executed, it will point to firstEffect again. The specific operations in the Layout stage will not be discussed in detail.

Summarize

EffectList is not a global variable. During the creation of the Fiber tree, Fiber nodes with effect are collected layer by layer. The final root node will collect all Fiber nodes with effect . We call this linked list containing effect nodes EffectList.

Since the collection process is depth-first, the children will be collected first, so the children will be operated first during traversal. Therefore, if an interviewer asks which of the child and parent life cycles or useEffect is executed first, you will clearly know that the child operation will be executed first.

The above is a brief analysis of the details of EffectList in React. For more information about EffectList in React, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • 5 things to note when writing React components using hooks
  • Implementation steps for setting up the React+Ant Design development environment
  • How to build a React project with Vite
  • React example of how to get the value of the input box
  • React implements the sample code of Radio component
  • How to use history redirection in React Router
  • Let's talk about my understanding and application of React Context
  • React hooks introductory tutorial
  • Detailed process of creating a VR panoramic project using React and Threejs

<<:  How to use multi-core CPU to speed up your Linux commands (GNU Parallel)

>>:  Django+mysql configuration and simple operation database example code

Recommend

How to upgrade CentOS7 to CentOS8 (detailed steps)

This article uses a specific example to introduce...

Summary of MySQL's commonly used concatenation statements

Preface: In MySQL, the CONCAT() function is used ...

Notes on the MySQL database backup process

Today I looked at some things related to data bac...

This article will show you how to use Vue 3.0 responsive

Table of contents Use Cases Reactive API related ...

MySQL 5.7 installation and configuration tutorial under CentOS7 (YUM)

Installation environment: CentOS7 64-bit, MySQL5....

Detailed explanation of the usage and function of MySQL cursor

[Usage and function of mysql cursor] example: The...

Eclipse configures Tomcat and Tomcat has invalid port solution

Table of contents 1. Eclipse configures Tomcat 2....

Analysis of uniapp entry-level nvue climbing pit record

Table of contents Preface Hello World image Set b...

How to capture exceptions gracefully in React

Table of contents Preface ErrorBoundary Beyond Er...

Several ways to clear arrays in Vue (summary)

Table of contents 1. Introduction 2. Several ways...

The vue project realizes drawing a watermark in a certain area

This article shares with you how to use Vue to dr...

About VSCode formatting JS automatically adding or removing semicolons

introduction It is okay to add or not add a semic...

Specific use of MySQL internal temporary tables

Table of contents UNION Table initialization Exec...

Introduction to encryption of grub boot program in Linux

Table of contents 1. What is grub encryption 2. g...