React在函数式组件中践行“代数效应”,用于将副作用从函数调用中分离。
React Fiber可以理解为:React内部实现的一套状态更新机制,支持任务不同优先级,可
中断与恢复,再恢复后可以服用之前的中间状态。
Fiber的含义
- 作为架构,之前的React15的Reconciler采用递归的方式执行,数据保存在递归调用栈中(stack Reconciler)。React16的Reconciler基于Fiber节点实现,被称为Fiber Reconciler。
- 作为静态的数据结构来说,每一个Fiber节点对应一个React element,保存该组件的类型(函数组件/类组件/原生组件…)对应的Dom节点等信息。
作为动态的工作单元来说,每一个Fiber节点保存是本次更新该组件改变的状态,要执行的工作(需要被删除/被插入页面中/被更新…)
Fiber结构
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
// 作为静态数据结构的属性
this.tag = tag;
this.key = key;
this.elementType = null;
this.type = null;
this.stateNode = null;
// 用于连接其他Fiber节点形成Fiber树
// 指向父级Fiber节点
this.return = null;
// 指向子Fiber节点
this.child = null;
// 指向右边第一个兄弟Fiber节点
this.sibling = null;
//index对于多个Fiber节点,表示他们插入Fiber的位置
this.index = 0;
this.ref = null;
// 作为动态的工作单元的属性
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
this.dependencies = null;
this.mode = mode;
this.effectTag = NoEffect;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
// 调度优先级相关
this.lanes = NoLanes;
this.childLanes = NoLanes;
// 指向该fiber在另一次更新时对应的fiber
this.alternate = null;
}
作为架构来说
每一个Fiber节点有一个对应的React element,多个Fiber节点连接。
依靠return、child、sibling属性
// 指向父级Fiber节点
this.return = null;
// 指向子Fiber节点
this.child = null;
// 指向右边第一个兄弟Fiber节点
this.sibling = null;
作为静态的数据结构,保存组件相关信息
// Fiber对应组件的类型 Function/Class/Host...
this.tag = tag;
// key属性
this.key = key;
// 大部分情况同type,某些情况不同,比如FunctionComponent使用React.memo包裹
this.elementType = null;
// 对于 FunctionComponent,指函数本身,对于ClassComponent,指class,对于HostComponent,指DOM节点tagName
this.type = null;
// Fiber对应的真实DOM节点
this.stateNode = null
作为动态的工作单元
```html // 保存本次更新造成的状态改变相关信息 this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; this.dependencies = null;
this.mode = mode;
// 保存本次更新会造成的DOM操作 this.effectTag = NoEffect; this.nextEffect = null;
this.firstEffect = null; this.lastEffect = null;
```html
// 调度优先级相关
this.lanes = NoLanes;
this.childLanes = NoLanes;