Features/functions of Fiber

Fiber makes animation, layout, and page interaction smoother.

I. Concept of Fiber

React Fiber is a new scheduling strategy for React rendering. JavaScript is single-threaded. Once a component starts updating, the main thread is controlled by React, and any interaction with React will get stuck.

React Fiber is an object that records updates that need to be made or have been made on a component. A component can correspond to multiple fibers. The React Element tree created in the Render function creates an identical structure of Fiber nodes when first rendered. Different React Element types correspond to different Fiber node types. A React Element is handled by its corresponding Fiber node. A React Element can correspond to more than one Fiber, because when Fiber updates, it clones a new Fiber(alternate) from the original Fiber(current). Side effects of two Fiber diff outputs are recorded on alternate. Therefore, when a component is updated, there will be at most two fibers corresponding to it. After the update, the alternate will replace the previous current, which is called the new current node. React Fiber Refactoring is a way to slice up the rendering process and take a break for each moment of execution. If a task with a higher priority comes, it will be executed first, reducing the possibility of page lag, and enabling React to better experience scenes with high real-time requirements such as animation.

Two: What is Fiber?

When JS is processing large computation, the page will appear the phenomenon of frame jam, and even more serious, the page will appear “false death”. So in these cases, will inevitably lead to animation frame loss, incoherence, user experience is particularly poor. In order to solve this problem, we can be big split into small calculation, and then according to the order of execution asynchronous calls, this is not a long time his thread, the UI can also calculate the execution of the gap in the two small updates, thus giving the user feedback in time, Fiber is to do so, and implemented in the form of a higher pretend bility. While React solved the problem of HOW to update views with the least DOM manipulation cost, Fiber also solved the problem of WHEN to update which parts of a view. Shard priority!!

For these reasons, Fiber implements a virtual call stack and prioritizes all updates as follows:

'use strict';

export type PriorityLevel = 0 | 1 | 2 | 3 | 4 | 5;

module.exports = {
 
	NoWork: 0.// No work is pending.
 
	SynchronousPriority: 1.// Used to control text input. Side effects of synchronization.

	AnimationPriority: 2.// This needs to be done before the next frame.
 
	HighPriority: 3.// It takes a quick interaction to generate a reaction.
 
	LowPriority: 4.// Retrieve data, or update stored results.
 
	OffscreenPriority: 5.// Will not be visible, but do the work in case it becomes visible.

};
Copy the code

The order of execution is then determined based on the priority of these updates. As you can see, animation and page interaction are high priority, which is one of the reasons Fiber makes animation, layout, and page interaction much smoother. Priority can be divided into synchronous and asynchronous tasks, including SynchronousPriority and TaskPriority, which are completed in the current frame. Tasks with asynchronous priorities, including HighPriority, LowPriority, and OffscreenPriority, may be completed in the next few frames. The React V16.3.2 priority is not divided into three types: NoWork, sync, and Async. The first two types are considered synchronous tasks that need to be completed in the current tick and expire at null. The last type of asynchronous tasks will be counted. ExpirationTime, in workLoop, according to the expirationTime to determine whether the next fragment task, scheduleWork update task priority, that is, update this context time. As for how to calculate this time, you can view the source code.

Iii. Basic principles of Fiber:

The task of updating the Reconcilition Phase is divided into two phases, the Reconciliation Phase and the Commit Phase. The Reconciliation Phase works by finding the Diff Fiber Tree, which is a computation Phase where the results can be cached and thus interrupted. Commit Phase commits all updates and renders, and is set to uninterruptible to prevent page jitter. PS: ComponentWillMount omponentWillReceiveProps componentWillUpdate Several lifecycle methods that are called in the Reconciliation Phase and have the potential to be broken. So it can be called multiple times. ShouldComponentUpdate can also be called multiple times, but it only returns true or false with no side effects and can be ignored for now.

4. Data structure of Fiber

Fiber is a linked list with child and sibing attributes that point to the first child node and adjacent siblings to form the Fiber tree. The return property points to its parent node. The update queue, updateQueue, is a linked list with first and last attributes pointing to the first and last update objects. Each fiber has an updateQueue attribute pointing to its corresponding updateQueue. Each fiber has an alternate property, starting with a clone body of its own. Update changes are first updated on alternate, and when the update is complete, alternate replaces current.

5. Implementation process of Fiber
  1. After setState is called due to user operation, enqueueSetState method is called first, which can be divided into two stages (personal understanding). The first stage is Data Preparation, which initializes some Data structures, such as Fiber, Update value and Update.
  2. The ensureUpdateQueues method initializes two update queues, queue1 and current. UpdateQueue. Queue2 and current. The alternate. UpdateQueue corresponding.
  3. In the second phase, Fiber Reconciler, task fragmentation scheduling began, and scheduleWork first updated the priority of each Fiber. There is no updatePriority method, but it did this. When fiber.return === null, find the parent node and attribute all diff side effects to root.
  4. RequestWork first adds the current update to the Schedule List (addRootToSchedule) and then asynchronously renders depending on whether the current render is asynchronous (isAsync parameter). ScheduleCallbackWithExpriation method, high-energy next!!!!!
  5. ScheduleCallbackWithExpriation this method in different environment, different implementation, such as chrome requestIdleCallback apis used by the browser, without the API browser, RequestAnimationFrame simulates a requestIdCallback to complete the next fragment when the browser is free. Note that this function will pass in a expirationTime after which the fragment will be discarded.
  6. Execute to performWorkOnRoot, which is the Commit Phase and Reconciliation Phase mentioned in fiber documentation.
  7. The first Reconciliation Phase, in the workLoop, completes each shard task through a while loop.
  8. Formunitofwork can also be divided into two phases, shown in blue. BeginWork is an entry function that instantiates different React Element classes based on the workInProgress type. WorkInProgress is obtained by alternate mounting some new properties.
  9. When instantiating different React Element classes, the lifecycle methods associated with Will are called.
  10. CompleteUnitOfWork does some finishing work, updates props and calls lifecycle methods after diff a node.
  11. Then enter the Commit Phase, which cannot be interrupted.
How does Fiber affect developers?
  1. ComponentWillMount componentWillReceiveProps, componentWillUpdate several life cycle method is no longer safe, due to the task execution process can be interrupted, this several life cycle may be executed multiple times, If they contain side effects (such as Ajax), unexpected bugs can occur. The React team provides an alternative lifecycle approach. It is recommended that if you use the above method, use pure functions as far as possible to avoid stepping on pits in the future.
  2. Note how react prioritizes task slices, especially when pages are animated.
  3. If there is always a higher-level task, fiber will perform the higher-level task first, and then go back to the previously half-rendered component via callback and start rendering from scratch. (It might seem unreasonable to discard the rendered life cycle and increase the render time, but react actually does this.)