Hi everyone, I'm Kasong.
Let's look at this article React
internal Effects List
mechanism reconstruction of cause and effect.
After reading this article, you can grasp the difference and reasons React18
compared to the previous version, Suspense
Welcome to join the human high-quality front-end frame group , take flight
What are side effects
The simple React
can be summarized as:
- Trigger
update
stage: Calculate the side effects
caused by the update of 161a97a2f5ae49
- commit phase: side effects of
side effects include many types, such as:
Placement
refers to the insertion and movement ofPassive
refers touseEffect
callback executionChildDeletion
refers to the removal of the childDOM node
- and many more
The main changes caused by the update to DOM
Placement
and ChildDeletion
.
So how does the render stage save the
side effects, and how does the
commit stage
side effects?
Effects List
Before reconstruction, in the render stage, nodes with side effects
will be connected to form a linked list, which is called
Effects List
.
For example, in the following figure, B, C, and E have side effects of , and the connection forms
Effects List
:
commit stage does not need to traverse the entire tree from A down, only need to traverse
Effects List
to find all nodes with side effects and perform corresponding operations.
SubtreeFlags
After the reconstruction, the side effects child node will be bubbled to the
SubtreeFlags
attribute of the parent node.
For example, the side effects contained in B, C, and E are as follows:
The bubbling process is as follows:
- The side effect of B’s
Passive
, bubbled to A,A.SubtreeFlags
containsPassive
- E's
side effect is
Placement
, bubbled to D,D.SubtreeFlags
containsPlacement
- D bubbles to C,
C.SubtreeFlags
containsPlacement
- C’s
side effect is
Update
,C.SubtreeFlags
containsPlacement
, C bubbling to A - The final
A.SubtreeFlags
containsPassive
,Placement
,Update
This means that A's subtree contains these three side effects.
In the commit phase, then according
SubtreeFlags
Finding layers side node and perform a corresponding operation.
It can be seen that SubtreeFlags
needs to traverse the tree, while Effects List
only needs to traverse the linked list, which is more efficient. So React
be refactored?
Suspense
The answer is: SubtreeFlags
operating traversal subtree although the ratio Effects List
need to traverse more nodes, but React18
in a new feature just need traverse the subtree .
This feature is Suspense
.
Suspense
is v16
to provide functionality, but v18
later, when concurrent open function, Suspense
previous versions of the behavior is different.
Consider the following components:
<Suspense fallback={<h3>loading...</h3>}>
<LazyCpn />
<Sibling />
</Suspense>
Wherein LazyCpn
using React.lazy
wrapped asynchronous loading assembly.
Sibling
code for 061a97a2f5b36e is as follows:
function Sibling() {
useEffect(() => {
console.log("Sibling effect");
}, []);
return <h1>Sibling</h1>;
}
Since Suspense
will wait for the asynchronous request in the descendant components to complete before rendering, when the code runs, the page will first render fallback
:
<h3>loading...</h3>
But Sibling
not asynchronous! This reflects the difference between the old and new version React
Differences between the old and new versions of React
Recall the working principle React
introduced at the beginning:
- Trigger
update
phase: The coordinator calculates the side effects
caused by the 161a97a2f5b497 update
- commit stage: the renderer executes
side effects
Before enabling concurrency, React
guarantees that a render stage corresponds to a
commit stage.
So in the above example, although due LazyCpn
in the request led to Suspense
rendering fallback
, but does not prevent Sibling
rendering, it will not prevent Sibling
in useEffect
executed.
The console will still print Sibling effect .
At the same time, in order to visually appear that Sibling
not rendered, the DOM node of Sibling
rendered by will be set to
display: none
:
But this is actually quite hack
. After all, according to Suspense
, if the descendant components have asynchronously loaded content, then only fallback
should be rendered (rather than the content of display: none
at the same time)
Therefore, in the new version, a separate process is for the subtree 161a97a2f5b5cf that is not displayed in Suspense
in , neither rendering the content of display: none
useEffect
callback:
The basis for this part of the process is to change the commit phase, which means returning to the
Effects List
mentioned in the opening refactoring to subtreeFlags
.
You can intuitively feel the difference between the new version and the old version Suspense
online Demo
Summarize
Today we learned a little knowledge of React
It is worth mentioning that, for Suspense
this improvement, as React
bring a new internal component type - Offscreen Component
.
In the future, he may be the basis for the React
version keep-alive
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。