Fiber

Points to note:

  • When the component is first runfibet mountStage; Later updated tofiber updatePhase.
  • Function componentmountfibet.tag 为 IndeterminateComponent 。
    • Legacy, older versions support function factory components, functions return one withrenderThe object of the function will be treated asClassComponentTo deal with. At this timetagAssign reassigns toClassCompoentOtherwise, it is assigned toFunctionComponent 
  • keyWill caststringType.
    • 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:
    • indiifwhenreconcileChildFibers() 为 jsxChildrencreatefiber 
    • Among themreuse fiber, the callcreateWorkInProgress()Switch,workInProgress
    • Unable to reuse the newly createdfiber, the callcreateFiberFromTypeAndProps()createfiber 
  • WorkInProgress:
    • workInProgress 是The old and new alternate.alternateIt’s where the old meets the new
      • The old and new Fiber objects are reused, not newly created, which should save memory
    • workInProgressIs thisupdateThe correspondingfiber ,
      • alternateIs 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 toalternateCan 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.currentIndicates that a program is in progressfiberThe tree

reference

React Technology revealed