7.Fiber architecture

Video explanation (efficient learning) :Into the study

Previous articles:

1. Introduction and questions

2. React design philosophy

React source code architecture

4. Source directory structure and debugging

5. JSX & core API

Legacy and Concurrent mode entry functions

7. Fiber architecture

8. Render phase

9. The diff algorithm

10. com MIT stage

11. Life cycle

12. Status update process

13. Hooks the source code

14. Handwritten hooks

15.scheduler&Lane

16. Concurrent mode

17.context

18 Event System

19. Write the React mini

20. Summary & Answers to interview questions in Chapter 1

Deep understanding of Fiber

React15 is unbreakable in reconcile during the render phase, which can cause gridlock when reconcilinglarge numbers of nodes because all browser time is being handed over to JS execution and JS execution is single threaded. Therefore, after React16, scheduler schedules time slices, giving each task (unit of work) a certain amount of time. If the task is not completed within this time, the execution right is also handed over to the browser for drawing and rearranging. Therefore, asynchronous and interruptible update requires certain data structure in memory to store the information of unit of work. This data structure is called Fiber.

So what can you do with a data structure like Fiber

  • Task decomposition of unit of work: The most important function of Fiber is as a unit of work, which stores the corresponding information (including priority) of the original node or component node. These nodes form a Fiber tree through the shape of Pointers
  • Incremental rendering: Generate minimal differential patches by comparing JSX objects with Current Fiber and apply them to real nodes
  • Pause, continue and arrange priority according to priority: The priority is saved in Fiber node, and the ability of pause, continue and arrange priority can be achieved through the comparison of priority of different nodes, which also provides the foundation for the upper layer to realize batch update and Suspense
  • ** Because Fiber stores state and updated information, it implements state updates for function components, which are hooks

Fiber data structure

Fiber has the following built-in properties:

//ReactFiber.old.js
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // Stores node information as a static data structure
  this.tag = tag;// The type of the corresponding component
  this.key = key;/ / the key attribute
  this.elementType = null;// Element type
  this.type = null;/ / func or class
  this.stateNode = null;// Real DOM node

  // Connect as a fiber tree
  this.return = null;// point to the parent node
  this.child = null;/ / points to the child
  this.sibling = null;// point to sibling nodes
  this.index = 0;

  this.ref = null;

  // Calculate state as a unit of work
  this.pendingProps = pendingProps;
  this.memoizedProps = null;
  this.updateQueue = null;
  this.memoizedState = null;
  this.dependencies = null;

  this.mode = mode;
    
	/ / is related to the effect
  this.effectTag = NoEffect;
  this.nextEffect = null;
  this.firstEffect = null;
  this.lastEffect = null;

  // Priority-related attributes
  this.lanes = NoLanes;
  this.childLanes = NoLanes;

  // Current and workInProgress Pointers
  this.alternate = null;
}
Copy the code

Fiber double cache

Now we know that Fiber stores the real DOM. The real DOM corresponds to the Fiber node in memory and forms a Fiber tree. The react tree is called the current Fiber tree. The Fiber tree under construction is called workInProgress Fiber, and the nodes of the two trees are connected through alternate.

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

ReactDOM.render(<App />.document.getElementById("root"));
Copy the code

Building the workInProgress Fiber occurs in createWorkInProgress, which can create or consume the Fiber

//ReactFiber.old.js
export function createWorkInProgress(current: Fiber, pendingProps: any) :Fiber {
  let workInProgress = current.alternate;
  if (workInProgress === null) {// Distinguish between mount and 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;// Reuse attributes
    workInProgress.type = current.type;
    workInProgress.flags = NoFlags;

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

  workInProgress.childLanes = current.childLanes;// Reuse attributes
  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;
}
Copy the code
  • On mount: fiberRoot and rootFiber are created, then Fiber nodes are created based on the JSX object and connected to the Current Fiber tree.

  • When the update: A Fiber tree called workInProgress will be formed based on the JSX (the render or FuncComponent return value of ClassComponent) and current Fiber (diff algorithm). Then point fiberRoot’s Current to the workInProgress tree, and the workInProgress becomes Current Fiber. FiberRoot: Indicates only one root node of the entire application

    FiberRoot: Indicates only one root node of the entire application

    RootFiber: Reactdom. render or reactdom. unstable_createRoot An application can have multiple nodes.

We now know that there are two Fiber trees, current Fiber and workInProgress Fiber, and Fiber double cache refers to, In Reconcile (diff), a new workInProgress Fiber is formed and then the workInProgress Fiber is switched to current Fiber and applied to the real DOM. The advantage of having two fibers is to form a view description in memory. In the end, it is applied to the DOM to reduce the dom operation.

Now look at the Fiber dual cache creation process:

  • The mount when:

    1. Initially, only fiberRoot and rootFiber nodes were created

    2. Then create workInProgress Fiber according to JSX:

    3. Switch the workInProgress Fiber to Current Fiber

  • When the update

    1. Create workInProgress Fiber based on Current Fiber
    2. Switch the workInProgress Fiber to Current Fiber