The model for handling priorities in React 16 is ExpirationTime, which uses a length of time to describe the priority of a task.
React 17, on the other hand, uses the Lane model to handle task priorities, which is able to cover more boundary conditions by assigning different priorities to a bit and manipulating the priorities through 31-bit bitwise operations. In short: a binary number is used to represent the priority of a task.
For the sake of completeness of understanding, this article starts with the three phases of the React architecture: schedule , diff and commit.
1. Schedule
1.1 Creating update tasks
An update task is created on first render and user-triggered event, assigned a priority, and placed in the fiber.updateQueue update pair and given to the Scheduler to schedule the update
fiber.updateQueue is a ring structure with a pending pointer to the last update. New update insertion process.
The ring structure is created so that the first and last nodes can be found at once
1.2 Priority
For interval priority, react uses a binary operation to determine if a lane is in an interval, up to 31 bits, each bit being a lane.
For example, to determine if a lane is in an interval.
Merge lane.
1.3 updateQueue execution
- Iterate through the
updateQueuechain to collect tasks in the current update task interval, i.e., calculate whetherlaneis in the current interval, and if not, put it intonewFirstBaseUpdate.... ...newLastBaseUpdateto defer execution. - Execute
update, i.e. calculate the newstatebygetStateFromUpdate, store the result innewState, and insert the remainingupdateafterlastBaseUpdate. - When the
updateQueueis finished, the final result is stored in thebaseState
1.4 Concurrency through time slicing
By time slicing, i.e., the task is decomposed into multiple units of work. For each completed unit of work, determine if there is a high priority job, and if so, let the browser interrupt the rendering
The time slicing effect can be simply implemented using requestIdleCallback.
To reduce commit execution (a user-aware process), react is designed to track fiber root, also known as progress root or wipRoot, and commit fiber to dom only once all work is done, i.e., when there is no next unit of work.
2. Diff
2.1 Building the tree
Generate element nodes with the CreateElement function
|
|
Common JSX nodes are the following
-
function components, which generate
elementnodes as -
Class component, whose generated
elementnode is. -
A native label or text node whose generated
elementnode is
2.1.1 Simulating the execution of the CreateElement function
The following function component should not be new to users who have developed react, so let’s use it as an example and learn
Convert to CreateElement function call
Executed and generated element nodes
Note that the children of the function component comes from the result of the function instead of props, i.e. children = type(props)
In this process, the returned TreeNode tree structure is [{...} ,{...}], is a normal tree structure based on recursive traversal and cannot achieve breakpoint back, while the Fiber chain table is constructed with 3 pointers for each fiber node, linked to its first child node child, next sibling node sibling and parent node return, and each fiber will become a working unit
2.2 Updating, Deleting
When we need to implement update and delete nodes, i.e. call setState, we need to compare the elements received in the render function with the last FiberTree submitted to dom. Therefore, we need to save the reference currentRoot of the last submission to FiberTree and add an alternate attribute to each fiber, recording the old fiber submitted in the previous stage
Note that the child creation process is accompanied by a comparison, i.e., old fiber is compared with new fiber while creating fiber for the element’s children
- If
old fiberandnew fiberhave the sametype, keep thedomnode and update itspropsand set the tageffectTagtoUPDATE. - If
typeis different and it isnew fiber, it means to create a newDOMnode and set the tageffectTagtoPLACEMENT; if it isold fiber, you need to delete the node and set the tageffectTagtoDELETION
To detect changes quickly, React uses key. This makes it faster to detect when a child element has changed its position in the array of elements key->fiber
3. commit phase
3.1 Create operation
Committing a create operation performs real dom generation and ref initialization.
3.2 Update operations
The update phase will set props to dom
3.3 Replace operation
Use the old node to find the parent node, then replace the dom node with the new dom node
3.4 Delete operation
The new node does not exist, indicating that the current node is deleted