Fiber is React’s new Reconciler design, which uses scheduling to address some of the previous stack Reconciler issues as well as some of the legacy issues. React uses Fiber Reconciler to render and update components starting with version V16.0.0.

Why Fiber

The render task for React was a synchronization task. The problem of a synchronization task is that other tasks need to wait when the synchronization task is executed. If the execution time of this task is too long, the task is blocked and other tasks cannot be executed in a timely manner. For example, when the page is rolled, the page is stuck.

What are the benefits of using Fiber for React

  1. You can control the rendering process yourself:
    1. The rendering task is split into task units to achieve incremental rendering.
    2. Task units can be paused, reused, and terminated.
    3. Task units can be prioritized by task type.
    4. Task units can be executed concurrently.
  2. Optimized performance:
    1. After solving the problem of continuously occupying the main thread, the experience performance of the page has been optimized, which is more suitable for some high experience requirements, such as animation display, gesture manipulation.
  3. To address issues left over from history:
    1. ComponentDidCatch life cycle function for easy handling of component exceptions.
    2. Support the Render () function to return array elements and extend Fragment components.

And these optimizations are basically insensitive to the user and do not block the user’s use.

How to realize Fiber

When rendering a React application, you are actually calling a function. The function itself calls other functions, creating a call stack. This recursive call creates a call stack that we have no control over. What Fiber does is make the function call stack run as needed, manually. So Fiber can be interpreted as reimplementation of the stack.

What changes did React make

1. Nodes are linked lists

First, Fiber nodes are linked to each other in a list, which is designed to simulate a function call stack. A node records its parent, child, and closest sibling. Compare this to a function call stack:

Function call stack Fiber
The basic unit function fiber node
The input Function parameters props
The local state The local variable state
The output Function return value react element
Call at a lower level Nested function calls child node
The higher calling The return address return node

As shown in the table above, the Fiber Node Tree, like the function call stack, stores the context of node processing so that we can manually control the node rendering process.

2. Create a Fiber Node for React Element

During reconciliation, a Fiber node is created for each React element returned by the Render method, forming a Fiber node tree. In subsequent updates, React reuses fiber nodes, And update its properties with data from the React Element. If the React Element returned from the Render method changes, React moves or deletes it based on the key. This is equivalent to changing the data structure of the tree node and adding many attributes:

  1. Describe hierarchy:
    1. Return, pointing to the parent node.
    2. Child, pointing to the first child node.
    3. Sibling, points to the next sibling node.
  2. StateNode holds the instance of the component.
  3. The types of side effects are related to the side effects linked list:
    1. EffectTag, the specific type of action that needs to be performed when changes are needed, such as Update or Placement.
    2. NextEffect, the next Fiber with side effects to deal with.
    3. FirstEffect and lastEffect, the first and last fibers in this Fiber subtree that have side effects.
  4. Update relevant:
    1. UpdateQueue, a queue that records status updates, callback functions, and DOM updates.
    2. MemoizedState, last updated Fiber’s State.
    3. MemoizedProps, last time UPDATE fiber props.
    4. PendingProps, the new props, will be used for props of child components or DOM elements.
  5. Remaining execution time related:
    1. ExpirationTime, the executable time of a task unit.
    2. ChildExpirationTime, which determines whether the subtree has yet to be modified.

3. The Effects list

React updates very quickly, and for high performance, it builds a list of fiber nodes that have side effects. It quickly iterates through nodes that need to be modified, much faster than the entire tree, and doesn’t have to spend time on nodes that don’t have side effects. The diagram below:

You can see how the nodes with effects are linked together. When traversing the nodes, React uses the firstEffect pointer to determine where the effects list starts. So the figure above can be represented as a linear linked list like this:

4. Double buffer

React double-buffering means that the workInProgress tree is built from the old Fiber tree to the new Fiber tree. Once the workInProgress tree is built and committed, the new Fiber tree is created. This reduces memory allocation and garbage collection. Not all nodes in the workInProgress tree are new. For example, a subtree does not need to be changed. React will reuse the subtree to reduce additional operations.

Double buffering also has the advantage of making it easier to handle exceptions thrown during rendering. When a node fails to render, the old fiber tree nodes can be used to avoid the entire render crashing.

5. The rendering process is divided into two stages

React Fiber’s rendering process is divided into render phase and Commit phase, which is equivalent to the previous DIff phase and patch phase.

What the Render phase does is iterate through the build workInProgress tree (fiber node tree in construction), marking the fiber nodes with the work that needs to be done in the COMMIT phase. In the COMMIT phase, the Effects linked list is processed and the real DOM tree is updated according to the node markers in the workInProgress tree. Once the workInProgress tree is rendered on the screen, it becomes the new Fiber node tree.

For life cycle functions, the life cycle functions that the Render phase goes through: [UNSAFE_] componentWillMount forthcoming (waste), [UNSAFE_] componentWillReceiveProps GetDerivedStateFromProps shouldComponentUpdate [UNSAFE_]componentWillUpdate (about to be deprecated) render The lifecycle functions that the COMMIT phase goes through are: getSnapshotBeforeUpdate, componentDidMount, componentDidUpdate, componentWillUnmount.

React expects manual control of the rendering process. You can pause, stop, and reuse the rendering process. React plans to disable some of the render lifecycle functions because the render process can be manually controlled so that the lifecycle functions can run multiple times during the Render phase. The commit phase, on the other hand, does the work in one go (synchronous tasks) without pausing, so try not to do complex calculations during these life cycles.

Why the Render phase can manually control the rendering process, while the Commit phase needs to do it all at once? Because of one of React’s core tenets: consistency, it always updates the DOM once and doesn’t display partial results. The Render phase is not visible to the user, so you can process the render task in pieces, whereas the Commit phase updates the changes to the DOM at once, so you need to do it all in one go.

6. Since realized window. RequestIdleCallback method

Window. RequestIdleCallback method, the function of itself is used to define when the browser the main thread of spare time to deal with the callback function. Fiber to ensure that the key is not blocking the main thread, a period of idle time to render every time distribution, time is up, look at the main thread is idle now browser, if it is continues to allocate a spare time to render, if not to stop the current rendering, give up the browser handle other tasks the main thread. So will be expected to use Windows. ReqeustIdleCallback method. However, since it is a new API, many browsers do not support it yet, and some issues mentioned that it is actually a bit too strict and not implemented frequently enough, with only 20 implementations per second, to ensure smooth UI rendering. Therefore, the React team decided to implement their own version using its ideas. Use the requestAnimationFrame method to simulate. However, the requestAnimationFrame method has a flaw: the callback function does not execute while the page is in the background, so a remedy is needed to use setTimeout to set a timer of 100ms to continue rendering.

A small summary

The React Fiber design has not yet gone into the source code level. The React Fiber design will affect other functions of React Fiber. I hope I can write about it later. I hope this article helped you understand React Fiber design. Feel free to leave any comments or suggestions in the comments section


Cover image by Ferenc Almasi on Unsplash