React 可以将多个 setState() 调用批处理到单个更新中以提高性能。
由于this.props 和this.state 可能会异步更新,因此您不应依赖它们的值来计算下一个状态。
来自https://reactjs.org/docs/react-component.html#setstate:
setState() 将组件状态更改入队并告诉 React
这个组件及其子组件需要重新渲染
更新状态。
将setState() 视为请求,而不是直接命令
更新组件。为了获得更好的感知性能,React 可能
延迟它,然后一次更新几个组件。反应
不保证立即应用状态更改。
通过示例了解
这个概念可能很难理解,特别是为什么它会导致问题,所以我写了一个例子来显示发生的错误:
/* Imagine props and states is the same as this.props and this.state */
var state = { counter: 0 } ; var props = { } ;
/* Our fake implementation of react setState */
var setStatesToRun = []
function setState(myFunction) { setStatesToRun.push(myFunction); }
/* Our fake implementation of react batch update */
function batchRunStateUpdates() {
propsLocal = props
stateLocal = state
f1 = setStatesToRun.pop()
newState = f1(stateLocal, propsLocal) // Will run increment by 3
console.log(newState) // newState: { counter: 3 }
console.log(state) // state: { counter: 0 }
f2 = setStatesToRun.pop()
newState = f2(newState, propsLocal) // Will run increment by 2
console.log(newState) // newState: { counter: 2 }
console.log(state) // state: { counter: 0 }
// ... get the next setState function loop
console.log("Will update global state")
state = newState
console.log(state) // state: { counter: 2 } // WRONG!
}
console.log(setStatesToRun) // []
// Right
setState((prevState, props) => { counter: prevState.counter + 3 });
// WRONG, using state (this.state)
setState((prevState, props) => { counter: state.counter + 2 });
console.log(setStatesToRun) // [func, func]
batchRunStateUpdates();
在顶部,我们有一些 React 方法的虚假版本。这些过于简化,但有助于解释发生了什么。
然后,我们像在 React 中一样使用 setState。一种用法是对的,另一种是错误的。
请注意,最终的全局状态应该是 state: { counter: 5 },但由于我们不尊重 React 的建议,我们得到了 state: { counter: 2 }
你可以在https://jsfiddle.net/oniltonmaciel/g96op3sy/玩这个代码