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, calls
requestIdleCallback api
When the browser is idle dom diff
The 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