This is the 30th day of my participation in the August Text Challenge.More challenges in August

🥸 problem

The JavaScript engine and the page rendering engine are mutually exclusive, and when one thread executes, the other can only hang and wait

If the JavaScript thread is tied to the main thread for a long time, the render level update will have to wait for a long time, and the interface will not be updated for a long time, resulting in poor responsiveness of the page and the user may feel stuck

And this is exactly the problem faced by the Stack Reconciler in React 15, when React renders components in a seamless process from start to completion, without interruption

If the component is large, the JS thread will execute until the entire VDOM tree has been evaluated before handing it to the rendering thread

This can lead to tasks such as user interactions, animations, and so on that can’t be handled immediately, resulting in a stuttering situation.

The emergence of the Fiber

React Fiber is a major change and optimization that Facebook has spent more than two years making on React. It is a re-implementation of the React core algorithm. React Fiber is being released in React 16, as confirmed from Facebook at the React Conf 2017 conference

React does the following:

  • A priority is added for each task, and a higher priority task can interrupt a lower priority task. Then re-execute the low-priority task
  • Added asynchronous tasks, callsrequestIdleCallback apiWhen the browser is idle
  • dom diffThe tree becomes a linked list, one DOM for two fibers (a linked list) for two queues, all for finding interrupted tasks and re-executing them

From an architectural perspective, Fiber is a rewrite of the React core algorithm, known as the harmonic process

From the perspective of encoding, Fiber is a data structure defined internally by React. It is the node unit of the Fiber tree structure, which is also the virtual DOM under the new React 16 architecture

Fiber is a JavaScript object that contains information about an element, its update queue, and its type. Its data structure looks like this:

type Fiber = {
  // The WorkTag type used to mark Fiber indicates the component type represented by fiber, such as FunctionComponent and ClassComponent
  tag: WorkTag,
  // ReactElement key
  key: null | string,
  // ReactElement. Type, the first argument to call createElement
  elementType: any,
  // The resolved function/class/ associated with this fiber.
  // Indicates the node type currently represented
  type: any,
  // Represents the element component instance corresponding to the current FiberNode
  stateNode: any,

  // Point to 'parent' in the Fiber tree to return up after processing the node
  return: Fiber | null.// point to your first child node
  child: Fiber | null.// The return of the sibling node points to the same parent node
  sibling: Fiber | null.index: number,

  ref: null | (((handle: mixed) = > void) & { _stringRef: ?string }) | RefObject,

  // The component props object in the current process
  pendingProps: any,
  // Props after the last rendering
  memoizedProps: any,

  // Updates generated by components of the Fiber are stored in this queue
  updateQueue: UpdateQueue<any> | null.// State from the last rendering
  memoizedState: any,

  // a list of fiber-dependent contexts
  firstContextDependency: ContextDependency<mixed> | null.mode: TypeOfMode,

  // Effect
  // To record Side Effect
  effectTag: SideEffectTag,

  // Single linked lists are used to quickly find the next side effect
  nextEffect: Fiber | null.// The first side effect in the subtree
  firstEffect: Fiber | null.// Last side effect in the subtree
  lastEffect: Fiber | null.// represents at what point in the future the task should be completed, after which the version was renamed to lanes
  expirationTime: ExpirationTime,

  // Quickly determine if there are any changes in the subtree that are not waiting
  childExpirationTime: ExpirationTime,

  // Fiber version pool, which records the fiber update process for easy recovery
  alternate: Fiber | null,}Copy the code

The effect of fiber

Fiber breaks up the render update process into sub-tasks, doing a little bit at a time to see if there’s time left, and if there’s time to move on to the next task; If not, suspend the current task, give time control to the main thread, and continue executing it when the main thread is less busy

In other words, it can interrupt and restore, and reuse the previous intermediate state after recovery, and assign different priorities to different tasks. The update unit of each task is the Fiber node corresponding to the React Element

The requestIdleCallback method implements the above approach

Window. RequestIdleCallback () method will be called function in browser free time line. This enables developers to perform background and low-priority work on the main event loop without affecting the delay of critical events such as animations and input responses

First, React tasks are divided into multiple steps and completed in batches. After completing a portion of the task, hand back control to the browser, giving it time to render the page again. React allows the browser to run out of time and then proceed with tasks left unfinished by React. This is a cooperative scheduling approach.

The implementation process is based on Fiber nodes. As a static data structure, each Fiber node corresponds to a React Element, which stores the type of the component (function component/class component/native component, etc.) and corresponding DOM node information.

As a dynamic unit of work, each Fiber node holds the component’s changed state and work to be performed during this update.

Each Fiber node has a React element. Multiple Fiber nodes build a tree based on three properties:

// point to the parent Fiber node
this.return = null
// Point to the sub-fiber node
this.child = null
// Point to the first sibling Fiber node on the right
this.sibling = null
Copy the code

These attributes are used to find the next execution target