Fiber
Points to note:
- When the component is first run
fibet
mountStage; Later updated tofiber
updatePhase. - Function component
mount
时fibet.tag
为IndeterminateComponent
。- Legacy, older versions support function factory components, functions return one with
render
The object of the function will be treated asClassComponent
To deal with. At this timetag
Assign reassigns toClassCompoent
Otherwise, it is assigned toFunctionComponent
- Legacy, older versions support function factory components, functions return one with
key
Will caststring
Type.key = '' + config.key;
export type Fiber = {|
/ / type eg: 0: FunctionComponent, 1: ClassComponent, 2: IndeterminateComponent
tag: WorkTag,
// fiber key
key: null | string,
// save type in diff
elementType: any,
// function/class/ eg: 'div'; function FC(); class C extend Component;
type: any,
// Host instance. DOM in the browser
stateNode: any,
// Fiber parent node
return: Fiber | null.// The first child node
child: Fiber | null.// Sibling nodes
sibling: Fiber | null.// Fiber is generated according to JSX.
// This fiber corresponds to the JSX, the position index in jsxChildren
// eg:
</App> The index of textareaFiber is 1
index: number,
/ / reference ref
ref:
| null
| (((handle: mixed) = > void) & {_stringRef:? string, ... }) | RefObject,pendingProps: any, // Props being evaluated in rendering
memoizedProps: any, // The props actually used. Can also be thought of as the props cache value of the last rendering.
// Update the queue class component to handle state; The function component is hooks Effect; Native (DOM) components are property variations;
updateQueue: mixed,
// The actual state used. You can also think of it as the state cache value from the last rendering.
memoizedState: any,
// Dependent context, event
dependencies: Dependencies | null.// 模式 eg: ConcurrentMode ; StrictLegacyMode
mode: TypeOfMode,
// Effect fiber
// Binary complement. To mark fiber's effect eg:Update Placment Deletion Ref related Hooks
flags: Flags,
// Effect set of subtrees for performance tuning. Eg: Skip the subtree directly for NoFlags
subtreeFlags: Flags,
// The child to be deleted
deletions: Array<Fiber> | null.// Has been discarded;
// The commit phase uses effectList to optimize performance
nextEffect: Fiber | null.firstEffect: Fiber | null.lastEffect: Fiber | null./ / priority
lanes: Lanes,
// Subtree priority
childLanes: Lanes,
/ / standby; Switch between newFiber and oldFiber;
alternate: Fiber | null.// use Profiler; Record update DurationactualDuration? : number, actualStartTime? : number, selfBaseDuration? : number, treeBaseDuration? : number,// dev debug_debugSource? : Source |null, _debugOwner? : Fiber |null, _debugIsCurrentlyTiming? : boolean, _debugNeedsRemount? : boolean, _debugHookTypes? :Array<HookType> | null|};Copy the code
Alternate toggle in Fiber — createWorkInProgress
Look at the function
function createWorkInProgress(current: Fiber, pendingProps: any) :Fiber {
let workInProgress = current.alternate;
// workInProgress === null indicates the mount phase
if (workInProgress === null) {
workInProgress = createFiber(
current.tag,
pendingProps,
current.key,
current.mode,
);
workInProgress.elementType = current.elementType;
workInProgress.type = current.type;
workInProgress.stateNode = current.stateNode;
// currentFiber connects to newFiber
workInProgress.alternate = current;
current.alternate = workInProgress;
} else {
/ / update phase
// Reuse some attributes
workInProgress.pendingProps = pendingProps;
workInProgress.type = current.type;
workInProgress.flags = NoFlags;
workInProgress.subtreeFlags = NoFlags;
workInProgress.deletions = null;
}
// null flags (except StaticMask)
workInProgress.flags = current.flags & StaticMask;
// Reuse some attributes
workInProgress.childLanes = current.childLanes;
workInProgress.lanes = current.lanes;
workInProgress.child = current.child;
workInProgress.memoizedProps = current.memoizedProps;
workInProgress.memoizedState = current.memoizedState;
workInProgress.updateQueue = current.updateQueue;
/ / clone dependencies
const currentDependencies = current.dependencies;
workInProgress.dependencies =
currentDependencies === null
? null
: {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
};
// Reuse some attributes
workInProgress.sibling = current.sibling;
workInProgress.index = current.index;
workInProgress.ref = current.ref;
return workInProgress;
}
Copy the code
- Timing:
- indiifwhen
reconcileChildFibers()
为jsxChildren
createfiber
- Among themreuse
fiber
, the callcreateWorkInProgress()
Switch,workInProgress
- Unable to reuse the newly created
fiber
, the callcreateFiberFromTypeAndProps()
createfiber
- indiifwhen
- WorkInProgress:
workInProgress
是The old and new alternate.alternate
It’s where the old meets the new- The old and new Fiber objects are reused, not newly created, which should save memory
workInProgress
Is thisupdateThe correspondingfiber
,alternate
Is the fiber corresponding to the last update (fiber displayed on the current page).
- Alternate switch diagram
update a b
0: current the first timenull<--alternate--> workInProgress WorkInProgress = current. Alternate workInProgress = createFiber() ↓ (Last workInProgress is this currentnullNeed to create fiber.1: workInProgress <--alternate--> current: ↓ workInProgress = current. Alternate2: current <--alternate--> workInProgress: workInProgress = current. Alternate ↓3: workInProgress <--alternate--> current
Copy the code
- On final rendering, switch directly to
alternate
Can be
const finishedWork: Fiber = root.current.alternate;
root.finishedWork = finishedWork;
root.finishedLanes = lanes;
commitRoot(root);
root.current = finishedWork; // execute in commitRoot
Copy the code
The head node of Fiber
// pseudo code emulation represents the header
root:FiberRootNode = {
current:Fiber = {
stateNode = root // this is a circular reference
memoizedState = {element:null} // This is the project JSX entry
updateQueue // Initialize updateQueue}}Copy the code
root.current
Indicates that a program is in progressfiber
The tree
reference
React Technology revealed