javascript - 为什么这是更新状态的有效方法?
问题描述
在 React文档中,它提到不应直接从当前状态计算下一个状态。这是因为状态更新是异步的,所以你不能保证你使用的是正确的状态值。
但是,在官方教程中,你会看到这个功能:
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
是state.history
和的函数state.stepNumber
。这与文档中提到的内容不矛盾,还是我遗漏了什么?
解决方案
在我看来,人们对此有点过于教条,但已经有足够的困难来追踪可能是合理的错误。最终,您必须知道为什么推荐它,以便知道在特殊情况下是否可以。
为什么推荐它?
状态更新是异步的并且可以成批的,如果您多次更新状态并且您的一个或多个更新是基于以前的值,您可能会使用陈旧的值。在功能组件中,您面临与陈旧闭包相同的风险。
状态应该更新 5 次但只增加一次的示例:
功能组件示例:
const {useState} = React;
const Example = () => {
const [value, setValue] = useState(0);
const onClick = () => {
[1,2,3,4,5].forEach(() => {
console.log('update');
setValue(value + 1);
});
}
return (
<div>
<button onClick={onClick}>Update 5 times</button>
<div>Count: {value}</div>
</div>
)
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
类组件示例:
const {useState, useEffect} = React;
class Example extends React.Component {
state = {
count: 0
}
onClick = () => {
[1,2,3,4,5].forEach(() => {
this.setState({count: this.state.count + 1});
});
}
render() {
return (
<div>
<button onClick={this.onClick}>Update 5 times</button>
<div>Count: {this.state.count}</div>
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
可以使用基于先前状态的正常状态更新吗?
这取决于您的用例。如果您绝对确定您只会更新一次状态,那么从技术上讲它是安全的。问题是,虽然今天它可能是安全的,但明天你或其他开发人员可能会在不知不觉中改变它......
归根结底,我认为您必须问自己:“我是否从不使用功能更新中获得任何额外的好处?”,如果是这样,那么了解未来错误的风险并采取行动(您可能应该记录它也很严重)。但几乎每次,答案都是使用功能更新。
推荐阅读
- nginx-config - nginx 从 web 服务器重定向到应用服务器中的 API,但 API 在不同的端口上运行
- javascript - JavaScript - 直到下一个函数完成为止
- javafx - 如何将序列号添加到我需要在 javafx 中添加可观察列表以便显示在表视图中的当前列表中
- php - Wordpress - 使用 Ajax 关注用户列表
- c# - c# - 为什么这个绘图处理程序循环多次?
- python - 根据元素的值替换元素的 for 循环
- android - 为 ConstraintLayout 组设置 alpha 值
- c++ - 如果我在下面的代码片段中添加 `delete[] d;`,为什么我会得到零?
- python - 如何抑制 matplotlib 轴中的主要标签 xticks?
- reactjs - ExpressJS/ReactJS 持久解构问题