stay React
Not long ago PR #21488 in , Core members Brian Vaughn Yes React
Some inside API
、 And inside flag
Make adjustments .
One of the most striking changes is :React
Entrance increase createRoot API
.
The industry interprets this change as :Concurrent Mode
( Hereinafter referred to as CM
) Will be stable in the near future , And in the official version .
React17
It's a transitional version , To stabilize CM
. once CM
Stable , that v18 It's going to speed up a lot .
It can be said from 18 Year to 21 year ,React
The main work of the team is around CM
In the , that :
CM
What is it? ?CM
Can solveReact
What's the problem? ?- Why experience fast 4 year , stride across 16、17 Two versions ,
CM
Is not stable ?
This article will answer .
CM What is it?
To understand CM
( Concurrent mode ) What is it? , The first thing you need to know is React
The running process of the source code .
React
It can be divided into two phases :
render
Stage
stay render
Stage accounting is the changing part of an update ( adopt diff Algorithm ), Because of the render
The function is called in this phase .
render
Stage Probably It's asynchronous ( Depending on the scenario that triggers the update ).
commit
Stage
stay commit
The stage will be render
The part of phase computation that needs to change is rendered in the view . Corresponding ReactDOM
I'll do it appendChild
、removeChild
etc. .
commit
Phase must be synchronous call ( This way users won't see incomplete rendering UI
)
We go through ReactDOM.render
The created app belongs to legacy
Pattern .
In this mode, once render
The stage corresponds to one commit
Stage .
If we pass ReactDOM.createRoot
( This is not available in the current stable version API
) The created application belongs to the one mentioned at the beginning CM
(concurrent
Pattern )
stay CM
Next , Update has the concept of priority ,render
Phase may be interrupted by high priority updates .
therefore render
The phase may repeat many times ( Be interrupted and start over ).
Maybe many times render
The stage corresponds to one commit
Stage .
Besides , There's another. blocking
Patterns are used to facilitate developers to learn from legacy
Mode transition to CM
.
You can start your Feature comparison See the features supported by different patterns :
Why CM?
got it CM
What is it? , So what's the use of him ? Why? React
The core team will take time 3 More years (18 Year begins ) To realize him ?
This has to be done from React
We're talking about .
We can get it from the official website React philosophy notice React
Design concept of :
We think ,React
Yes, it isJavaScript
structure Respond quickly Large scaleWeb
The preferred way for applications .
among Respond quickly It's the point .
So what impact Respond quickly Well ?React
The answer given by the team :
CPU
The bottleneck andIO
Bottleneck
CPU Bottleneck
Consider the following demo
, Let's play up 3000 List items of :
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);
Just said , stay legacy
In mode render
The stage is not interrupted , Then this 3000 individual li
Of render
All have to be done in the same browser macro task .
Long time computation can block threads , Causes the page to drop the frame , This is it. CPU
Bottleneck .
The solution is : Enable CM
, take render
The stage becomes interruptible Of ,
When the browser does not have much time left in a frame, the control is given to the browser . Wait for the spare time of the next frame to continue the component render
.
IO Bottleneck
In addition to the long calculation caused by the stuck , When the network requests loading
State also makes the page non interactive , This is it. IO
Bottleneck .
IO
The bottleneck is objective .
As front-end , All you can do is request the data you need as soon as possible .
however , Usually : Code maintainability And Request efficiency It's contrary .
What does that mean , for instance :
Suppose we encapsulate the method of requesting data useFetch
, Distinguish whether to request data by the existence of return value .
function App() {
const data = useFetch();
return {data ? <User data={data}/> : null};
}
In order to improve the Code maintainability ,useFetch
With the component to render User
Exist in the same component App
in .
However , If User
You need to further request data in the component ( as follows profile
data )?
function User({data}) {
const {id, name} = data?.id || {};
const profile = useFetch(id);
return (
<div>
<p>{name}</p>
{profile ? <Profile data={profile} /> : null}
</div>
)
}
In line with Code maintainability principle ,useFetch
With the component to render Profile
Exist in the same component User
in .
however , So organize the code ,Profile
Components can only wait User
render
Later render
.
Data can only be like waterfall water , One layer at a time .
This inefficient way of requesting data is called waterfall
.
In order to improve the Request efficiency , We can “ request Profile
Operation of data required by component ” mention App
In component , Merge in useFetch
in :
function App() {
const data = useFetch();
return {data ? <User data={data}/> : null};
}
But that reduces Code maintainability (Profile
Component separation profile
The data is too far away ).
React
Team from Relay
The team learns from experience , With the help of Suspense
characteristic , Put forward Server Components.
Just to deal with IO
When it comes to bottlenecks Code maintainability And Request efficiency .
The implementation of this feature requires CM
in Updates have different priorities .
CM Why did it take so long ?
Next , We from Source code
、 characteristic
、 ecology
Three aspects , From the bottom up CM
How difficult it is to popularize .
Source level
Priority algorithm transformation
stay v16.13 Before ,React
Basic... Has been achieved CM
function .
We talked about ,CM
There is the concept of update priority . Before it was through a millisecond expirationTime
Mark to update The expiration time of .
- By comparing different updated
expirationTime
Judge the priority - By comparing the updated
expirationTime
Determine whether the update is expired with the current time ( Expiration needs to be synchronized )
however ,expirationTime
As a time-dependent floating-point number , Can't express A batch of priorities The concept .
In order to achieve a higher level of Server Components
characteristic , Need to have A batch of priorities The concept .
therefore , Core members Andrew Clark Started a long-term priority algorithm transformation , see :PR lanes
Offscreen Support
At the same time , Another member Luna Ruan Developing a new API
—— Offscreen
.
Understandably, this is React
Version of Keep-Alive
characteristic .
Subscribe to external sources
Did not open CM
front , In one update, the following three lifecycles are called only once :
componentWillMount
componentWillReceiveProps
componentWillUpdate
But turn on CM
after , because render
The phase may be interrupted 、 repeat , So they can be called many times .
Subscribing to external sources ( For example, registering event callbacks ) when , May not be updated in time or memory leak .
for instance :bindEvent
It's based on Publish subscribe The external dependence of ( Like a native DOM
event ):
class App {
componentWillMount() {
bindEvent('eventA', data => {
thie.setState({data});
});
}
componentWillUnmount() {
bindEvent('eventA');
}
render() {
return <Card data={this.state.data}/>;
}
}
stay componentWillMount
In the binding , stay componentWillUnmount
Untie in .
When an event is received , to update data
.
When render
The stages are repeatedly interrupted 、 After suspension , Possible :
Before the event is finally bound (
bindEvent
Before execution ), The event source triggered the event
here App
The component has not registered the event yet (bindEvent
Not yet implemented ), that App
Acquired data
It's the old one .
To solve this potential problem , Core members Brian Vaughn Developed features :create-subscription
Used in React
To standardize the subscription and update of external sources .
In short, it is to register and update external sources in commit
Phase is bound to the component's state update mechanism .
At the characteristic level
When Source level After the support of , be based on CM
The development of new features of is put on the agenda .
This is Suspense
.
[[Umbrella] Releasing Suspense #13206](https://github.com/facebook/r...PR
Responsible for the record Suspense
The development of properties .
Umbrella
The mark represents thisPR
Will affect a lot of Libraries 、 Components 、 Tools
You can see , A long timeline from 18 It's been a few years until the last few days .
first Suspense
It's just Front end features , at that time React SSR
It can only be passed forward character string data ( It's also known as dehydration
)
later React
A set of SSR
Components of time streaming Transfer protocol , Sure streaming Transport components , Not just HTML
character string .
here ,Suspense
Given more responsibilities . It also has more complex priorities , This is what I just said Priority algorithm transformation A big reason for .
The final result , It was launched earlier this year Server Components
Concept .
On the ecological level
When Source level Support 、 characteristic And the development is complete , Is it possible to connect seamlessly ?
Still early .
As a ship 8 The great ship of the year ,React
Every time I upgrade to the final community popularization , There's a lot of work to do in the middle .
To help the community make a slow transition to CM
,React
We have done the following work :
- Development
ScrictMode
characteristic , And it's enabled by default , Standardize the way developers write - take
componentWillXXX
Marked asunsafe
, Remind users not to use , Will be scrapped in the future - A new life cycle (
getDerivedStateFromProps
、getSnapshotBeforeUpdate
) Replace, for example, the life cycle that will be abandoned - Developed
legacy
Patterns andCM
Intermediate mode of transition ——blocking
Pattern
And this , It's just in the interim The most simple Part of .
The hard part is :
A lot of the current accumulation in the community is based on
legacy
How to migrate the library of pattern ?
A lot of animation Libraries 、 State Management Library ( such as mobX
) It's not a simple migration .
summary
We introduced CM
The context of his life and the difficulties of his migration .
Through this article , I'm sure you know that the first one is React
increase createRoot
( Turn on CM
Methods ) It's not easy .
Fortunately, everything is worth it , In the past React
The barrier to success is : Open source is early 、 The community is big .
So from CM
Start ,React
Probably It's going to be the most complex view framework in the front end .
When the , There won't be any React-like
The framework can realize React
alike feature
.
But others say ,CM
These functions are chicken ribs , I don't need to .
You feel CM
What about? ? Welcome to leave your discussion .