setState
因为批量更新存在异步的可能,取的 this.state/this.props
不一定是预期的最新值,使用 componentDidUpdate
或者 setState
的回调函数都可以保证在组件重渲染完成后执行,这时 state
是最新的。
以上是我理解,但具体什么时候使用回调函数来更新 state
呢?React 官方文档的一些线索是
如果后续状态取决于当前状态,我们建议使用 updater 函数的形式代替
https://zh-hans.reactjs.org/d...我应该如何更新那些依赖于当前的 state 的 state 呢?
给 setState 传递一个函数,而不是一个对象,就可以确保每次的调用都是使用最新版的 state
https://zh-hans.reactjs.org/d...
那么是否可以理解为依赖当前 state
的要用回调函数,但在 React 的教程实现 Toc Tac Toe 的代码中却并不是这样的
handleClick(i) {
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
history: history.concat([{
squares: squares
}]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext,
});
}
代码中对 history
和 xIsNext
的计算都依赖于当前的 state 但并没有使用回调函数。
所以 setState
回调函数具体要在什么时机使用呢?
并没有什么黑科技,把你上面的代码结合到下面的react batching逻辑中马上就能理解了
如果是第一个参数是对象则state不会立即发生变化所以下面这种做法可能会不符合预期
看上去加了三次一实际上只有最后一次生效了也就相当于只加了一次一(详细逻辑看上面代码)
而后续的setState要想获得之前setState对state做的变更,只需要参数传函数就行
处理updateQueue时的调用栈

processUpdateQueue源码
getStateFromUpdate源码
处理不同类型的payload源码