React source code analysis 7.Fiber architecture
Video explanation (efficient learning): enter learning
Past articles:
3.react source code architecture
4. Source directory structure and debugging
Legacy and concurrent mode entry function
19. Handwritten mini version of react
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"));
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.
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:
:
- At the beginning, only two nodes, fiberRoot and rootFiber, were created
- Then create workInProgress Fiber according to jsx:
- Switch workInProgress Fiber to current Fiber
- At the beginning, only two nodes, fiberRoot and rootFiber, were created
update
- Create workInProgress Fiber based on current Fiber
- Switch workInProgress Fiber to current Fiber
- Create workInProgress Fiber based on current Fiber
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。