首先在 setState 说的异步,指不能立刻获取到更新的数据 那么什么条件下会发生,何时又是同步的 这个分版本 在react 17中是 定时器,监听事件回调里都是同步的也就是说在里面设置完数据后,就能立刻获取到最新的数据。
setTimeout(() => {
this.setState({
count: this.state.count + 1
}, () => {
console.log('callback', this.state.count)
})
console.log('state', this.state.count)
}, 100);
但是在react 18 中,定时器,监听事件回调里都是异步加合并,也就是说,统一了行为。
合并
- 但是合并在react 版本中行为都是一致的
- 对于纯数值类型,多次更新,但是每次都是获取的初始值,可以理解为每次当前函数上下文,是同一个引用的是首次的初始值。
- 但是对于函数类型,那就不是,每次 都是在原有的基础上进行更新
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
<button onClick={() => {
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
// this.setState((prevState) => {
// return {
// count: prevState.count + 1
// }
// })
// this.setState((prevState) => {
// return {
// count: prevState.count + 1
// }
// })
// this.setState((prevState) => {
// return {
// count: prevState.count + 1
// }
// })
console.log('state', this.state.count) // 1
setTimeout(() => {
this.setState({
count: this.state.count + 1
}, () => {
console.log('callback', this.state.count)
})
console.log('state', this.state.count)
}, 100);
}}>点击</button>
不可变
- 本质上是说函数式编程里面的纯函数,同样的输入造成同样的输出,你直接修改了输入,那就可能难以追踪数据修改。
- 同时也为了性能优化,比如会常用immer.js
- 不过里面所提到的原理层面为何一定要用不可变,用了不可变又会发生什么
错误的做法:
this.state.obj1.a = 100
this.state.obj2.a = 100
this.setState({
obj1: this.state.obj1,
obj2: this.state.obj2
})
正确的做法:
this.setState({
obj1: Object.assign({}, this.state.obj1, {a: 100}),
obj2: {...this.state.obj2, a: 100}
})