2

React source code analysis 7.Fiber architecture

Video explanation (efficient learning): enter learning

Past articles:

1. Opening introduction and

2. The design concept of

3.react source code architecture

4. Source directory structure and debugging

5.jsx & core api

Legacy and concurrent mode entry function

7. Fiber architecture

8.render stage

9.diff algorithm

10.commit phase

11. Life cycle

12. Status update process

13.hooks source code

14. Handwritten hooks

15.scheduler&Lane

16.concurrent mode

17.context

18 event system

19. Handwritten mini version of react

20. Summary & Answers to

21.demo

Deep understanding of Fiber

The reconcile of react15 in the render stage is uninterruptible, which may cause a stutter when a large number of nodes are reconcile, because all the time of the browser is handed over to the execution of js, and the execution of js is single-threaded. For this reason, after react16, there is a scheduler to schedule time slices, and each task (unit of work) is given a certain amount of time. If the execution is not completed within this time, the execution rights must be handed over to the browser for drawing and rearrangement. Therefore, asynchronous interruptible update requires a certain data structure in memory to save the information of the work unit, and this data structure is Fiber.

So what can be done with the data structure of Fiber?

  • work unit task decomposition : The most important function of Fiber is as a work unit, saving the corresponding information (including priority) of native nodes or component nodes. These nodes form a Fiber tree through the shape of pointers
  • incremental rendering : through the comparison of the jsx object and the current fiber, generate the smallest difference patch, and apply it to the real node
  • pauses, resumes, and prioritizes according to priority : The priority is saved on the Fiber node. Through the comparison of the priority of different nodes, the ability to pause, continue, and prioritize tasks can also be achieved for the upper level. Suspense provides the foundation
  • save state: Because Fiber can save state and updated information, it can realize the state update of function components, that is, hooks

Fiber data structure

Fiber's own attributes are as follows:

//ReactFiber.old.js
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  //作为静态的数据结构 保存节点的信息 
  this.tag = tag;//对应组件的类型
  this.key = key;//key属性
  this.elementType = null;//元素类型
  this.type = null;//func或者class
  this.stateNode = null;//真实dom节点

  //作为fiber数架构 连接成fiber树
  this.return = null;//指向父节点
  this.child = null;//指向child
  this.sibling = null;//指向兄弟节点
  this.index = 0;

  this.ref = null;

  //用作为工作单元 来计算state
  this.pendingProps = pendingProps;
  this.memoizedProps = null;
  this.updateQueue = null;
  this.memoizedState = null;
  this.dependencies = null;

  this.mode = mode;
    
    //effect相关
  this.effectTag = NoEffect;
  this.nextEffect = null;
  this.firstEffect = null;
  this.lastEffect = null;

  //优先级相关的属性
  this.lanes = NoLanes;
  this.childLanes = NoLanes;

  //current和workInProgress的指针
  this.alternate = null;
}

Fiber double buffer

Now we know that Fiber can save the real dom. The real dom corresponding to the Fiber node in the memory will form a Fiber tree. This Fiber tree is called current Fiber in React, which is the Fiber tree corresponding to the current dom tree, and the Fiber is being constructed. The tree is called workInProgress Fiber, and the nodes of the two trees are connected by alternate.

function App() {
  return (
        <>
      <h1>
        <p>count</p> xiaochen
      </h1>
    </>
  )
}

ReactDOM.render(<App />, document.getElementById("root"));

react源码7.2

Build workInProgress Fiber occurs in createWorkInProgress, it can create or consume Fiber

//ReactFiber.old.js
export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
  let workInProgress = current.alternate;
  if (workInProgress === null) {//区分是在mount时还是在update时
    workInProgress = createFiber(
      current.tag,
      pendingProps,
      current.key,
      current.mode,
    );
    workInProgress.elementType = current.elementType;
    workInProgress.type = current.type;
    workInProgress.stateNode = current.stateNode;
   
    workInProgress.alternate = current;
    current.alternate = workInProgress;
  } else {
    workInProgress.pendingProps = pendingProps;//复用属性
    workInProgress.type = current.type;
    workInProgress.flags = NoFlags;

    workInProgress.nextEffect = null;
    workInProgress.firstEffect = null;
    workInProgress.lastEffect = null;
    
    //...
  }

  workInProgress.childLanes = current.childLanes;//复用属性
  workInProgress.lanes = current.lanes;

  workInProgress.child = current.child;
  workInProgress.memoizedProps = current.memoizedProps;
  workInProgress.memoizedState = current.memoizedState;
  workInProgress.updateQueue = current.updateQueue;

  const currentDependencies = current.dependencies;
  workInProgress.dependencies =
    currentDependencies === null
      ? null
      : {
          lanes: currentDependencies.lanes,
          firstContext: currentDependencies.firstContext,
        };

  workInProgress.sibling = current.sibling;
  workInProgress.index = current.index;
  workInProgress.ref = current.ref;


  return workInProgress;
}
  • When mounting: FiberRoot and rootFiber will be created, then Fiber nodes will be created based on the jsx object, and the nodes will be connected to the current Fiber tree.
    react源码7.1
  • During update: According to the new state, jsx (ClassComponent's render or FuncComponent's return value) will be compared with current Fiber (diff algorithm) to form a fiber tree called workInProgress, and then the current of fiberRoot will point to the workInProgress tree. workInProgress becomes current Fiber. fiberRoot: refers to the root node of the entire application, only one exists

    fiberRoot: refers to the root node of the entire application, only one exists

    rootFiber: There can be multiple nodes of the application created by ReactDOM.render or ReactDOM.unstable_createRoot.

    We now know that there are two Fiber trees, current Fiber and workInProgress Fiber. Fiber double buffering means that after reconcile (diff), a new workInProgress Fiber is formed and then workInProgress Fiber is switched to current Fiber and applied to the real dom. The advantage of Fiber is that the description of the view is formed in the memory, which is finally applied to the dom, reducing the operation of the dom.

Now let's take a look at the process diagram Fiber double cache creation:

  • :

    1. At the beginning, only two nodes, fiberRoot and rootFiber, were created
      react源码7.6
    2. Then create workInProgress Fiber according to jsx:
      react源码7.7
    3. Switch workInProgress Fiber to current Fiber
      react源码7.8
  • update

    1. Create workInProgress Fiber based on current Fiber
      react源码7.9
    2. Switch workInProgress Fiber to current Fiber

react源码7.8


zhang_a111
42 声望5 粉丝