划重点
- 不要直接修改state
- state更新可能是异步的
在React掌控内是异步(生命周期, react合成事件内),此外都是同步(宏任务,微任务,原生事件);异步的目的在于批量更新 - state更新可以被合并
参数为function时不会合并
直接修改state会怎么样?
// 错误示范, 此代码不不会重新渲染组件
this.state.comment = 'Hello';
// 正确使⽤用
this.setState({comment: 'Hello'});
setState 异步,同步?
- 异步
// 当setState在合成事件中(React事件中)
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 }
}
handleClick = () => {
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 0
}
render() {
console.log(this.state.counter, 'render') // 1
return (<>
<p>{this.state.counter}</p>
<button onClick={this.handleClick}>add</button>
</>);
}
}
/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
1 "render"
- 同步
// 如果把setState放置在宏任务中
setTimeout(() => {
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 1
}, 0)
/** log **/
// 首次加载
0 "render"
// 点击click
1 "render"
1 "handleClick"
// setState在原生事件中的表现
componentDidMount() {
document.documentElement.addEventListener('click', () => {
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 1
})
}
/** log **/
// 首次加载
0 "render"
// 点击click
1 "render"
1 "handleClick"
tips: 该规律同样使用与useState, 感兴趣的小伙伴可以一试
state的更新合并
handleClick = () => {
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 0
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 0
this.setState({ counter: this.state.counter + 1 })
console.log(this.state.counter, 'handleClick') // 0
}
/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
0 "handleClick"
0 "handleClick"
1 "render"
handleClick = () => {
this.setState((state) => ({ state, counter: state.counter + 1 }))
console.log(this.state.counter, 'handleClick') // 0
this.setState((state) => ({ state, counter: state.counter + 1 }))
console.log(this.state.counter, 'handleClick') // 0
this.setState((state) => ({ state, counter: state.counter + 1 }))
console.log(this.state.counter, 'handleClick') // 0
}
/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
0 "handleClick"
0 "handleClick"
3 "render"