Hello everyone, I'm Casson.
Compared with 0621f1d08419df, Vue
can be compiled based on the template. , React
is a full runtime library, and can running.
Most of these optimizations are developers, but they often confuse developers when they perform performance optimization on projects. For example the following code:
function App {
const [num, updateNum] = useState(0);
console.log('App render', num);
useEffect(() => {
setInterval(() => {
updateNum(1);
}, 1000)
}, [])
return <Child/>;
}
function Child() {
console.log('child render');
return <span>child</span>;
}
How many pieces of information will be printed after the App
component is mounted?
This article explains the performance optimization strategy React
inside Demo
Online Demo address
Welcome to join human high-quality front-end framework group , with flying
The effect of performance optimization
If the optimization strategy is not considered, the code running logic is as follows:
App
component first timerender
, print App render 0- child component
Child
firstrender
, print child render - After 1000ms, the
setInterval
callback is triggered andupdateNum(1)
executed App
component againrender
, print App render 1- child component
Child
againrender
, print child render - Repeat steps 3 to 5 every 1000ms
In fact, we will find that repeating steps 3 to 5 will not produce any changes, and there is obviously room for optimization here.
For this situation, React
did optimize. The above Demo
will be printed in sequence:
- App render 0
- child render
- App render 1
- child render
- App render 1
The confusing point here is: why after num
changes from 0 to 1, App render 1
is executed twice, while child render
is executed only once?
Next, we explain the above reasons from the perspective of theoretical and actual .
Theory of performance optimization
A noun is mentioned in the useState document : bailout .
He means: when useState
updated by state
is the same as the current state of (using
Object.is
comparison), React
will not be the descendant component render
of component.
Note: After hitting bailout
, the current component may still be render
, but his descendant component will not be render
.
This is because, in most cases, only the current components render
and useState
will be executed, so that state
can be calculated and then compared with the current state of .
As far as our Demo
is concerned, only App render
and useState
can be executed to calculate num
:
function App {
// useState执行后才能计算出num
const [num, updateNum] = useState(0);
// ...省略
}
In useState not bailing out when state does not change #14994 , Dan
also reiterates this point.
So from a theoretical perspective, in our Demo
in, num
from the 1 to a 0, Child the render performed only once is understandable, because App
hit bailout
, then he subcomponents Child
not render
.
But bailout
is only for the descendant component of the target component, so why for the target component App
, App render 1
is not executed after 2 executions?
The actual performance optimization strategy is more complicated.
Practical performance optimization strategies
The workflow of React
can be simply summarized as:
- Interactions (such as
click events,
useEffect
) trigger updates - Component tree
render
The bailout
just mentioned occurs in step 2: after the component tree starts render
, the descendant components of the component that hit bailout
will not be render
.
In fact, there is an optimization strategy that to : when step 1 triggers the update, it is found that state
not changed, then step 2 will not be continued at all.
From our Demo
:
function App {
const [num, updateNum] = useState(0);
console.log('App render', num);
useEffect(() => {
setInterval(() => {
updateNum(1);
}, 1000)
}, [])
return <Child/>;
}
Normally, updateNum(1)
executes, triggering an update. The new num of will not be calculated until
App render
and useState
executed, and then compared with the current num of to determine whether
bailout
is hit.
If updateNum(1)
executed, the new num of is calculated immediately, and then compared with the current num of
. If they are equal, the component tree will not be
render
.
This strategy of the timing of calculating state by , called eagerState
(eager state
).
Summarize
To sum up, our Demo
is the result of mixing these two optimization strategies:
- App render 0 (miss policy)
- child render
- App render 1 (miss policy)
- child render
- App render 1 (hit
bailout
) - (hit
eagerState
) - (hit
eagerState
)
......
For the implementation details of bailout
, please refer to the React component render .
Due to limited space, the implementation details of eagerState
will be discussed in a separate article.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。