What is Fiber?

The simplest and most intuitive way to think about it is that Fiber is the virtual DOM in React. But such an understanding is incomplete and inappropriate.

🚩 as a JS object, a Fiber node corresponds to a React Element, which stores information such as component type, props, and corresponding DOM node. This is the virtual DOM corresponding to each node of the view. However, the term “virtual DOM” is a misnomer in React. React supports multiple platforms, and DOM is just one of them. So React is just Fiber.

🚩, as a framework, is the Fiber Reconciler realized by React16 based on Fiber, in order to solve the problems inherent in the React15 Stack Reconciler, React implements:

  • Slicing up tasks to support interruption and recovery
  • Adjust priorities
  • Reset and reuse tasks
  • Stop working if you don’t need to

🚩 as the minimum unit of work for time sharding, each Fiber node holds the props of the component’s changed state and the work to be performed, added, updated, or deleted in this update

The structure of the Fiber

Fiber in React is a FiberNode class, representing a Fiber node. Learn about the properties of a FiberNode from the following three layers

Attributes associated with a DOM node

As a virtual DOM node, a FiberNode holds information about the element through the following properties:

  • Tag: indicates the type of the component
  • Type: for FunctionComponent, function itself, for ClassComponent, class, and for HostComponent, DOM node tagName
  • Key: Indicates the key attribute
  • elementType
  • StateNode: real DOM node corresponding to Fiber

Properties related to the Fiber architecture

Fiber is a linked list structure that concatenates children, siblings, and parents through three properties. When traversing the component tree in the Render stage, the following three attributes can not only connect the whole tree according to the father-son sibling relationship between nodes, but also realize the interruption and recovery of traversal.

  • Child: points to the first child Fiber node
  • Sibling: Points to the first sibling Fiber node
  • Return: Points to the parent Fiber node

A component instance has at most two corresponding Fiber nodes, one for the currently rendered DOM node (not available at mount stage) and the other for the workInProgress Fiber in progress. These two fiber nodes point at each other through alternate.

  • alternate

Priority correlation

  • lanes
  • childLanes

Properties related to update process state

The process of updating each Fiber node, as a separate task, updates one Fiber node each time the browser is idle, then transfers control back to the browser and updates the next Fiber node if there is time to ensure that the thread is not tied up for too long.

Since the tree is traversed intermittently, the state needs to be saved in the nodes, and the following fields hold the state changes for this update

  • pendingProps
  • memoizedProps
  • updateQueue
  • memoizedState
  • dependencies
  • mode

Save information about this DOM update operation

  • flags
  • subtreeFlags
  • deletions

How the Fiber architecture works

Front knowledge

Double cache Fiber tree

As mentioned above, a component instance has at most two corresponding Fiber nodes, corresponding to the whole application, that is, there are two Fiber trees, each node is associated with each other through alternate.

In React15, Reconciler and Renderer work alternately, and the entire process is synchronous. In Act16, the dual-cache Fiber tree is used, and the workInProgress tree is committed once it is built in memory, which is asynchronous and interruptible.

In the mount phase, fiber nodes do not have alternate equivalents. Therefore, you can determine whether the current phase is mount or update by checking whether alternate is null.

During the Update phase, the old and new Fiber nodes are compared to determine whether the old node can be reused. This process of comparison is called the Diff algorithm. Once a complete tree is built, submit it to the browser once again for rendering, and replace the current tree as a new current tree.

FiberRoot and rootFiber

FiberRoot is the root node of the entire application, which is always unique and has a Current property pointing to rootFiber, representing the Current Fiber tree

RootFiber is the root node of the fiber tree where
is located, and its child points to the corresponding fiber node of App. Each update call to reactdom.render creates a new rootFiber pointing to the workInProgress tree.

The working process of the

Take this code as an example:

function App() {
  const [num, add] = useState(0);
  return <div onClick={()= > add(num + 1}>{num}</div>
}
ReactDOM.render(<App />.document.getElementById('app'));
Copy the code

Mount stage

The first execution of Reactdom.render creates fiberRoot and rootFiber, with FiberRoot. current pointing to rootFiber, which has no children yet.

Next comes the Render phase, which creates a new rootFiber, then iterates through the subcomponents, creating fiber nodes, and finally building a Fiber tree

This is the process of asynchronous update, starting from rootFiber and traversing down the depth first, call the beginWork method to create sub-fiber nodes for the traversed fiber nodes, and connect the two fiber nodes. During the Update phase, old sub-fiber nodes are reused directly if the nodes are reusable or priority is insufficient.

When traversing the leaf node, completeWork is called to process the Fiber node, and different processing logic is called according to Fiber. Tag. This process is also divided into mount/update stages, mainly processing props, registering callback functions, and checking whether DOM nodes need to be generated. In the update phase, fiber.effectTag is set and saved to the effectList. In the mount phase, new DOM nodes are generated and sub-DOM trees are inserted into the currently generated DOM node to build a WIP tree. You are done building the DOM tree and simply insert the root node into the page.

When a fiber node completes completeWork, if it has a fiber sibling, i.e., fiber.sibling! If == null, the beginWork is called for its sibling fiber node, repeating the previous steps. If no sibling exists, the parent fiber node calls completeWork. Finally, back to rootFiber, you are done building the workInProgress tree.

In the above process, each call to beginWork/completeWork completes processing of a fiber node, assigns the value of the returned node to workInProgress, and then gives control back to the browser, which continues processing when the browser is idle; otherwise, the task is interrupted and resumed until the next idle time. This process of splitting the updates of the entire tree into nodes for processing is called time slicing.

The completed workInProgress Fiber tree is rendered to the page during the COMMIT phase, and FiberRoot.Current is then pointed to the workInProgress tree as the Current tree for comparison in the next update.

The update phase

When the user interaction triggers the state change, a new round of render phase will start and a new workInProgress tree will be constructed. During the construction process, each node will associate and compare with each node in the current Fiber tree through alternate. Decide whether to reuse the Current Fiber node.

Similarly, after the workInProgress tree is built, enter the COMMIT phase, and then update FiberRoot.Current to point to the workInProgress tree.

reference

  • React Technology revealed
  • Official source code overview