本文基于版本17.0.2和18
同步还是异步
setState
本身逻辑并不是由异步逻辑实现
在setState之后console.log打印的值并不是最新的值、由于批处理,状态变化是异步的
不同模式下表现是不一样的
- react17同步模式
ReactDOM.render
中如果在异步里是同步的,否则是异步的 - react18异步模式
ReactDOM.createRoot
中是都是异步更新的
批处理
是什么
在批处理下,你可能不会得到想到的结果
jsxthis.setState({ num: this.state.num + 1 }); this.setState({ num: this.state.num + 2 }); this.setState({ num: this.state.num + 3 }); #等于 Object.assign( previousState, {num: state.num + 1}, {num: state.num + 2}, {num: state.num + 3} ) #结果+3
为什么
如果每一次setState都去重新渲染更新视图,那么对性能有非常大的影响
具体表现
在react17,异步(setTimeout)或者绕过react组件(addEventListener)的不会进行批处理
jsximport "./styles.css"; import React, { Component } from "react"; export default class App extends Component { state = { num: 1 }; handleClick = () => { // setTimeout(() => { // this.setState({ num: this.state.num + 1 }); // this.setState({ num: this.state.num + 1 }); // console.log(this.state.num); // }); }; componentDidMount() { document.querySelector("button").addEventListener("click", () => { this.setState({ num: this.state.num + 1 }); this.setState({ num: this.state.num + 1 }); console.log(this.state.num); }); } render() { return ( <div className="App"> <h2>{this.state.num}</h2> <button onClick={this.handleClick}>111</button> </div> ); } }
怎么获取最新的state值
react17
在class component下
-
setState用函数写法
-
setState回调函数获取最新
-
setTimeout
-
addEventListener(不推荐)
在function下
- useEffect
react18
在class component下
-
setState用函数写法
-
setState回调函数获取最新
在function下
- useEffect
总结
- 在react18以前,setState只有在原生和setTimeout是可以立即获取值的
- setState执行过程和代码是同步的,但是由于事件合成、批处理无法立即拿到更新后的值,形成了异步、