React 将多个状态更新分组到一个重新渲染中以获得更好的性能。
同步代码块的会合并,promise
、setTimeout
、event
回调函数中会立刻渲染不会进行合并。
任何情况都可以合并渲染了,包括 promise
、setTimeout
、event
。
如果需要调用后立即重新渲染,使用flushSync
包裹。
import React from 'react';
import { Button, Space } from 'antd';
export default class ClassCom extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
handlerClick = () => {
this.setState({ count: this.state.count + 1 });
console.log(this.state.count);
setTimeout(() => {
console.log(this.state.count);
this.setState({ count: this.state.count + 3 });
console.log(this.state.count);
this.setState({ count: this.state.count + 4 });
console.log(this.state.count);
}, 0);
this.setState({ count: this.state.count + 2 });
console.log(this.state.count);
}
render() {
return (
<div>
<Space>
<Button onClick={this.handlerClick}>setState click</Button>
<p>count: {this.state.count}</p>
</Space>
</div>
);
}
}
React@18 渲染结果
// console 打印
0
0
2
2
2
// 最终 count 结果
6
// 0 + 1
// 0 + 2
// 2 + 3
// 2 + 4
React@17 渲染结果
import React, { useState } from 'react';
import { Button, Space } from 'antd';
export default function HooksCom() {
const [count, setCount] = useState(0);
const handlerClick = () => {
setCount(count + 1);
console.log(count);
setTimeout(() => {
console.log(count);
setCount(count + 3);
console.log(count);
setCount(count + 4);
console.log(count);
}, 0);
setCount(count + 2);
console.log(count);
};
return (
<div>
<Space>
<Button onClick={handlerClick}>useState click</Button>
<p>count: {count}</p>
</Space>
</div>
);
}
React@18 渲染结果
React@17 渲染结果
这里为什么 react@18 中,函数组件的输出结果为 0 0 0 0 0
渲染 4
,而类组件输出结果为 0 0 2 2 2
渲染 6
?
类组件中,this.state.count
是会根据 this
而改变的。而函数组件中,count
在 setTimeout
中不会改变,所以一直是 0
。
批量更新 render 影响
添加一个 render 组件
import { useEffect } from 'react';
export default function RenderEl() {
useEffect(() => {
console.log('useEffect render');
}, []);
console.log('render');
return null;
}
加到上面两种类型的组件中
<div>
<Space>
<Button onClick={this.handlerClick}>setState click</Button>
<p>
count: {this.state.count}
<RenderEl />
</p>
</Space>
</div>
再次点击渲染观察打印结果。
React@18 渲染结果
React@17 渲染结果
React@18 渲染结果
React@17 渲染结果
因篇幅问题不能全部显示,请点此查看更多更全内容