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
updateQueue
chain to collect tasks in the current update task interval, i.e., calculate whetherlane
is in the current interval, and if not, put it intonewFirstBaseUpdate.... ...newLastBaseUpdate
to defer execution. - Execute
update
, i.e. calculate the newstate
bygetStateFromUpdate
, store the result innewState
, and insert the remainingupdate
afterlastBaseUpdate
. - When the
updateQueue
is 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
element
nodes as -
Class component, whose generated
element
node is. -
A native label or text node whose generated
element
node 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 fiber
andnew fiber
have the sametype
, keep thedom
node and update itsprops
and set the tageffectTag
toUPDATE
. - If
type
is different and it isnew fiber
, it means to create a newDOM
node and set the tageffectTag
toPLACEMENT
; if it isold fiber
, you need to delete the node and set the tageffectTag
toDELETION
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