In PR # React
shortly before , the core member Brian Vaughn React
some API
and the internal flag
.
One of the most noticeable changes is: React
entrance of createRoot API
.
The industry interprets this change as: Concurrent Mode
(hereinafter referred to as CM
) will be stable in the near future and appear in the official version.
React17
is a transitional version to stabilize CM
. Once CM
stable, the progress of v18 will be greatly accelerated.
It can be said that from 18 to 21 years, the main work of the React
CM
out around 060b62f628be62, then:
CM
is 060b62f628bed9?- What problem can
CM
React
CM
not stable after almost 4 years, across 16 and 17 versions?
This article will answer.
What is CM
To understand what CM
(concurrent mode) is, you first need to know the running process of the React
React
can be roughly divided into two working phases:
render
stage
In the render
stage, the changed part of an update is calculated (through the diff algorithm), which is named after the render
render
stage may asynchronous (depends on the trigger scenes updates).
commit
stage
In commit
stage will render
required phase variation calculating section view rendering. Corresponding to ReactDOM
appendChild
, removeChild
etc. will be executed.
commit
phase must be called synchronously (so that the user will not see the incompletely rendered UI
)
The application we ReactDOM.render
belongs to the legacy
mode.
In this mode, one render
corresponds to one stage commit
If we pass ReactDOM.createRoot
(not this current stable version API
) application created belong mentioned at the beginning CM
( concurrent
mode)
Under CM
, the update has the concept of priority, and the render
phase may be interrupted by high-priority updates.
So the render
stage may be repeated many times (restarted after being interrupted).
render
stage may correspond to the commit
stage multiple times.
In addition, there is a blocking
mode for developers to slowly legacy
mode to CM
.
You can see the features supported by different modes feature comparison
Why do you need CM?
Knowing what CM
is, then what is his use? Why does the React
core team take more than 3 years (beginning in 18 years) to realize him?
This has to start React
the design concept of 060b62f628c199.
We can from the official website React philosophy see React
design concept:
We believe thatReact
is the first choice toJavaScript
build a fast response largeWeb
Among them, quick response is the focus.
So what affects rapid response to ? The answer given by the React
CPU
bottlenecks andIO
bottlenecks
CPU bottleneck
Consider the following demo
, we render 3000 list items:
function App() {
const len = 3000;
return (
<ul>
{Array(len).fill(0).map((_, i) => <li>{i}</li>)}
</ul>
);
}
const rootEl = document.querySelector("#root");
ReactDOM.render(<App/>, rootEl);
As mentioned earlier, in the legacy
mode, the render
stage will not be interrupted, so these 3000 li
render
must be completed in the same browser macro task.
Long-term calculations will block the thread and cause the page to drop frames. This is the bottleneck of CPU
The solution is: enable CM
, change the render
stage to to interrupt ,
When the remaining time of one frame of the browser is short, the control will be handed over to the browser. Wait for the free time of the next frame before continuing the component render
.
IO bottleneck
loading
caused by long-term calculations, the 060b62f628c360 state of the network request will also cause the page to be IO
, which is the bottleneck of 060b62f628c362.
IO
bottleneck of 060b62f628c37e is objective.
As a front end, all you can do is request the required data as soon as possible.
However, under normal circumstances: code maintainability and request efficiency are contradictory.
What do you mean, for example:
Suppose we encapsulate the method useFetch
for requesting data, and distinguish whether the data is requested by whether the return value exists.
function App() {
const data = useFetch();
return {data ? <User data={data}/> : null};
}
In order to improve the maintainability , useFetch
and the component User
to be rendered exist in the same component App
.
However, what if further data is required in the User
profile
data below)?
function User({data}) {
const {id, name} = data?.id || {};
const profile = useFetch(id);
return (
<div>
<p>{name}</p>
{profile ? <Profile data={profile} /> : null}
</div>
)
}
In the maintainability principle, useFetch
with the component to be rendered Profile
exist in the same assembly User
in.
However, if the code is organized in this way, the Profile
component can only wait for User
render
and then render
.
Data can only flow down layer by layer like water in a waterfall.
This inefficient way of requesting data is called waterfall
.
In order to improve request efficiency , we can "request Profile
assembly operations required data" mentioned App
inner assembly, incorporated useFetch
in:
function App() {
const data = useFetch();
return {data ? <User data={data}/> : null};
}
But this reduces the maintainability (the Profile
component is too far away from the profile
data).
React
team Relay
from the experience of the Suspense
feature to propose Server Components .
It is for the code maintainability and request efficiency when IO
bottleneck.
The realization of this feature requires the CM
update in have a different priority .
Why does CM take so long?
Next, from the source code,
features, and
ecology
CM
is to popularize 060b62f628c5d4 from the bottom up.
Source code level
Priority algorithm transformation
Before v16.13, React
has realized the basic CM
function.
As we talked about before, CM
has the concept of update priority. Preceded by a number of milliseconds expirationTime
numerals update expiration time.
- Judge the priority by comparing different updated
expirationTime
- Judge whether the update has expired by comparing the updated
expirationTime
with the current time (expiration needs to be executed synchronously)
However, expirationTime
as a time-related floating point number, cannot represent the concept of batch priority
In order to achieve the higher-level Server Components
feature, the concept of batch priority
Therefore, the core member Andrew Clark began a long-term priority algorithm transformation, see: PR lanes
Offscreen support
In the meantime, another member of the Luna Ruan in the development of a new API
- Offscreen
.
It can be understood that this is the Keep-Alive
feature React
Subscribe to external sources
CM
is turned on, the following three life cycles will only be called once in one update:
componentWillMount
componentWillReceiveProps
componentWillUpdate
But open CM
, due render
stage may be interrupted, repeat, so they may be called multiple times.
When subscribing to external sources (such as registering event callbacks), the updates may not be timely or memory leaks.
For example: bindEvent
is an publish and subscribe (such as a native DOM
event):
class App {
componentWillMount() {
bindEvent('eventA', data => {
thie.setState({data});
});
}
componentWillUnmount() {
bindEvent('eventA');
}
render() {
return <Card data={this.state.data}/>;
}
}
Bind in componentWillMount
and unbind in componentWillUnmount
.
When the event is received, update data
.
When the render
stage is repeatedly interrupted and suspended, it may appear:
Before the event is finally bound (before bindEvent
executed), the event source triggered the event
At this time, the App
component has not registered the event ( bindEvent
not been executed yet), so the App
obtained by data
is the old one.
In order to solve this potential problem, the core member Brian Vaughn developed a feature: create-subscription
Used to standardize the subscription and update of external sources React
Simply put, the registration and update of external sources are bound to the state update mechanism of the component commit
Characteristic level
When the support at the source level of is complete, the CM
will be on the agenda.
This is Suspense
.
[[Umbrella] Releasing Suspense #13206] ( https://github.com/facebook/react/issues/13206), this PR
is responsible for recording the progress of the Suspense
Umbrella
tag means that thisPR
will affect a lot of libraries, components, and tools
It can be seen that the long timeline has been from 18 years to the last few days.
Initially Suspense
was only front-end feature , at that time React SSR
string data to the front end (also commonly known as dehydration)
Later React
achieve a SSR
assembly when streaming transmission protocol stream transmission component, rather than HTML
string.
At this time, Suspense
was given more responsibilities. It also has a more complex priority, which is one of the reasons why priority algorithm
The final result is the Server Components
concept launched earlier this year.
Ecological level
When source level of supported, and feature is also developed, can it be seamlessly connected?
It's still early.
As a huge ship that has been running for 8 years, React
is upgraded to the final community popularity, there is a huge amount of work to do in the middle.
In order to help the community slowly transition to CM
, React
done the following:
- Develop the
ScrictMode
feature, and it is enabled by default, to standardize the developer's writing - Mark
componentWillXXX
unsafe
, remind users not to use it, it will be discarded in the future - Proposed new life cycles (
getDerivedStateFromProps
,getSnapshotBeforeUpdate
) to replace the life cycle that will be obsolete as above - Developed an
legacy
mode betweenCM
transition-blocking
mode
And this is just the simplest part
The hard part is:
How to migrate legacy
model currently accumulated in the community?
The migration of many animation libraries and state management libraries (such as mobX
) is not easy.
to sum up
We introduced the CM
and the difficulties of his migration.
Through this article, you must also know how React
add createRoot
(the way to turn on CM
) at the beginning.
Fortunately, everything is worth it. If React
were in the past: the open source time was early and the community was large.
So starting from CM
, React
may be will be the most complex view frame in the front-end field.
By then, there will not be any React-like
framework that can achieve the same React
feature
.
But some people say that CM
are tasteless, and I don't need them at all.
What do you think of CM
? Welcome to leave your discussion.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。