setState简述

用于更新用户界面以响应事件处理器和处理服务器数据的主要方式:setState()

1
setState(updater[, callback])

setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。

将 setState() 视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。

setState() 并不总是立即更新组件,它会批量推迟更新。这使得在调用 setState() 后立即读取 this.state 成为了隐患。为了消除隐患,请使用 componentDidUpdate 或者 setState 的回调函数(setState(updater, callback)),这两种方式都可以保证在应用更新后触发。

除非 shouldComponentUpdate() 返回 false,否则 setState() 将始终执行重新渲染操作。如果可变对象被使用,且无法在 shouldComponentUpdate() 中实现条件渲染,那么仅在新旧状态不一时调用 setState()可以避免不必要的重新渲染

1.参数一为带有形参的 updater 函数:

1
(prevState, props) => stateChange

prevState 是对应用变化时组件状态的引用。当然,它不应直接被修改。你应该使用基于 prevState 和 props 构建的新对象来表示变化。例如,假设我们想根据 props.step 来增加 state:

1
2
3
this.setState((prevState, props) => {
return {counter: prevState.counter + props.step};
});

updater 函数中接收的 prevState 和 props 都保证为最新。updater 的返回值会与 state 进行浅合并。

2.setState() 的第二个参数为可选的回调函数,它将在 setState 完成合并并重新渲染组件后执行。通常建议使用 componentDidUpdate() 来代替此方式。

1
2
3
4
5
this.setState((prevState, props) => {
return {counter: prevState.counter + props.step};
}, () => {
console.log('~~~~~counter', this.state.counter); // 更新后的counter
});

3.setState() 的第一个参数除了接受函数外,还可以接受对象类型:

1
setState(stateChange[, callback])

stateChange 会将传入的对象浅层合并到新的 state 中,例如,调整购物车商品数:

1
this.setState({quantity: 2})

这种形式的 setState() 也是异步的,并且在同一周期内会对多个 setState 进行批处理。例如,如果在同一周期内多次设置商品数量增加,则相当于:

1
2
3
4
5
6
Object.assign(
previousState,
{quantity: state.quantity + 1},
{quantity: state.quantity + 1},
...
)

后调用的 setState() 将覆盖同一周期内先调用 setState 的值,因此商品数仅增加一次。如果后续状态取决于当前状态,建议使用 updater 函数的形式代替:

1
2
3
this.setState((state) => {
return {quantity: state.quantity + 1};
});

篇外总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
handleGoodsImport = () => {
this.setState(prevState => ({
bulkGoodsOpen: !prevState.bulkGoodsOpen,
uploadStatus: '0'
}), () => {
console.log('~~~bulkGoodsOpen', this.state.bulkGoodsOpen)
})
} // good
handleGoodsImport = () => {
this.setState({
bulkGoodsOpen: !this.state.bulkGoodsOpen,
uploadStatus: '0'
}, () => {
console.log('~~~bulkGoodsOpen', this.state.bulkGoodsOpen)
})
} // bad
有关更多详细信息,请参阅:

本篇参阅

State 和生命周期指南

深入学习:何时以及为什么 setState() 会批量执行?

深入:为什么不直接更新 this.state?

0%