Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/408.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么这是更新状态的有效方法?_Javascript_Reactjs - Fatal编程技术网

Javascript 为什么这是更新状态的有效方法?

Javascript 为什么这是更新状态的有效方法?,javascript,reactjs,Javascript,Reactjs,在React中,它提到不应该直接从当前状态计算下一个状态。这是因为状态更新是异步的,所以不能保证使用了正确的状态值 但是,在官方网站中,您将看到此功能: handleClick(i) { const history = this.state.history.slice(0, this.state.stepNumber + 1); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

在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
的函数。这不是与文档中提到的内容相矛盾,还是我遗漏了什么?

因为:
const history=this.state.history.slice(0,this.state.stepNumber+1)实际上并没有改变任何状态。它只是将其分配给一个常量,供本地函数使用。它实际上并不是在操纵国家本身

下面几行使用
this.setState({})
以标准方式直接更改状态


对常量的赋值不同于您刚才所做的:
this.state.history.slice(0,this.state.stepNumber+1)
,这将直接操作它

,因为:
const history=this.state.history.slice(0,this.state.stepNumber+1)实际上并没有改变任何状态。它只是将其分配给一个常量,供本地函数使用。它实际上并不是在操纵国家本身

下面几行使用
this.setState({})
以标准方式直接更改状态


对常量的赋值不同于您刚才所做的:
this.state.history.slice(0,this.state.stepNumber+1)
,这将直接操纵它

在我看来,人们对它有点太武断了,但是已经有足够多的困难来跟踪错误,这可能是合理的。最后,您必须知道为什么建议使用,才能知道在特殊情况下是否可以不使用

为什么建议这样做? 状态更新是异步的,可以批处理,如果多次更新状态,并且一个或多个更新基于以前的值,则可能使用过时的值。在一个功能组件中,您面临着与过时闭包相同的风险

示例,其中状态应更新5次,但仅递增一次:

功能组件示例:

const{useState}=React;
常量示例=()=>{
const[value,setValue]=useState(0);
const onClick=()=>{
[1,2,3,4,5]。forEach(()=>{
console.log('update');
设置值(值+1);
});
}
返回(
更新5次
计数:{value}
)
}
ReactDOM.render(,document.getElementById('root'))

在我看来,人们对此有点过于武断,但已经有足够多的困难来追踪bug,也许这是合理的。最后,您必须知道为什么建议使用,才能知道在特殊情况下是否可以不使用

为什么建议这样做? 状态更新是异步的,可以批处理,如果多次更新状态,并且一个或多个更新基于以前的值,则可能使用过时的值。在一个功能组件中,您面临着与过时闭包相同的风险

示例,其中状态应更新5次,但仅递增一次:

功能组件示例:

const{useState}=React;
常量示例=()=>{
const[value,setValue]=useState(0);
const onClick=()=>{
[1,2,3,4,5]。forEach(()=>{
console.log('update');
设置值(值+1);
});
}
返回(
更新5次
计数:{value}
)
}
ReactDOM.render(,document.getElementById('root'))


可能是本教程过于简化的一种情况。或者可能是文档错误。如果是后者,则可以在上报告。我可以假设handleClick(单击回调)将是更改的状态触发器。。。然后,访问应用一个切片的值,将复制所需历史数组的一部分,并且计算不会因此受到影响。它是一个onclick处理程序,因此不存在批处理状态更新的风险,批处理状态更新在这里无论如何都不重要,因为如果您快速执行多个移动,使它们得到批处理,让其中一个丢失并被另一个移动覆盖并不重要(而且可能是期望的效果),这可能是本教程过于简化的情况。或者可能是文档错误。如果是后者,则可以在上报告。我可以假设handleClick(单击回调)将是更改的状态触发器。。。然后,访问应用一个切片的值,将复制所需历史数组的一部分,并且计算不会因此受到影响。它是一个onclick处理程序,因此不存在批处理状态更新的风险,批处理状态更新在这里无论如何都不重要,因为如果您快速执行多个移动,使它们得到批处理,让其中一个丢失并被另一个移动覆盖并不重要(而且可能是期望的效果)。感谢您提供的详细答案。然而,必须有一个中间立场。在这种情况下,如果我们遵循
setState
的函数形式,我们是否必须将所有与
history
相关的逻辑放在
setState
中?这看起来不太干净,我怀疑这是应该怎么做的。是的,你是对的,我不是说这需要在这里发生。更新的范围是有限的,这意味着风险也是有限的。我的观点是要了解每种方法的优缺点。在这种情况下,可读性可能会超过未来更新破坏内容的风险?在涉及bug之前,没有绝对的答案。同意。虽然我只是想用一种干净的方式来做这件事:使用外部状态更新函数。丹对此有一条很棒的推特,但因为我在手机上,所以无法连接atm。本质上,您使用功能更新,但是