反应setState不立即更新

reactjs React.js

小胖LEY西门

2020-03-19

我正在做一个待办事项应用程序。这是违规代码的非常简化的版本。我有一个复选框:

 <p><input type="checkbox"  name="area" checked={this.state.Pencil}   onChange={this.checkPencil}/> Writing Item </p>

这是调用复选框的函数:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }); 
  this.props.updateItem(this.state);
}

updateItem是映射为分派到redux的函数

function mapDispatchToProps(dispatch){
  return bindActionCreators({ updateItem}, dispatch);
}

我的问题是,当我调用updateItem操作并在console.log状态时,它总是落后1步。如果未选中该复选框且该复选框不为true,则仍将状态为true传递给updateItem函数。我需要调用另一个函数来强制状态更新吗?

第2320篇《反应setState不立即更新》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

8个回答
凯神乐 2020.03.19

Ben对于如何解决眼前的问题有很好的答案,但是我也建议您避免重复状态

如果状态处于redux中,则您的复选框应从prop或存储中读取其自身的状态,而不是同时在其自己的组件和全局存储中跟踪检查状态

做这样的事情:

<p>
    <input
        type="checkbox"
        name="area" checked={this.props.isChecked}
        onChange={this.props.onChange}
    />
    Writing Item
</p>

一般规则是,如果您在多个地方找到需要的状态,则将其提升到一个公共父级(并非总是重做),以保持只有一个真实来源

卡卡西神无西门 2020.03.19

尝试这个

this.setState({inputvalue: e.target.value}, function () {
    console.log(this.state.inputvalue);
    this.showInputError(inputs[0].name);
}); 

使用任何形式的showInputError函数进行验证

TomLEY 2020.03.19

我同时使用了rossipedia和Ben Hare的建议,并做了以下工作:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
   }, this.updatingItem); 
}

updatingItem(){
    this.props.updateItem(this.state)
}
猿村村 2020.03.19

setState()由于各种原因(主要是性能),React中的调用是异步的。在幕后,React将把多个调用分批处理setState()成一个状态突变,然后一次重新渲染组件,而不是针对每个状态更改重新渲染。

幸运的是,解决方案非常简单- setState接受一个回调参数:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }, function () {
      this.props.updateItem(this.state);
  }.bind(this));
}
L木嘢 2020.03.19

您应该调用第二个函数作为setState的回调,因为setState异步发生。就像是:

this.setState({pencil:!this.state.pencil}, myFunction)

但是,在您的情况下,由于您希望使用参数来调用该函数,因此您将不得不变得更有创造力,并且可能创建自己的函数来在道具中调用该函数:

myFunction = () => {
  this.props.updateItem(this.state)
}

将它们结合在一起,它应该可以工作。

番长小胖 2020.03.19

首先设定您的价值。完成您的工作之后。

this.setState({inputvalue: e.target.value}, function () {
    this._handleSubmit();
}); 

_handleSubmit() {
   console.log(this.state.inputvalue);
   //Do your action
}
LEYJim 2020.03.19

这是因为它异步发生,所以在那个时候可能还没有更新...

根据React v.16文档,您需要使用第二种形式,setState()形式接受函数而不是对象:

状态更新可能是异步的

React可以将多个setState()调用批处理到单个更新中以提高性能。

由于this.props和this.state可以异步更新,因此您不应依赖于它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要解决此问题,请使用setState()的第二种形式,该形式接受函数而不是对象。该函数将先前的状态作为第一个参数,而将更新时的props作为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
Eva理查德阳光 2020.03.19

当使用当前状态的属性更新状态时,React文档建议您使用函数调用版本setState而不是对象。

所以setState((state, props) => {...})代替setState(object)

原因是setState更多的是请求状态更改,而不是立即更改。React将这些setState要求批量化以提高性能。

这意味着您要检查的状态属性可能不稳定。这是一个潜在的陷阱。

有关更多信息,请参见此处的文档:https : //facebook.github.io/react/docs/react-component.html#setstate


为了回答您的问题,我会这样做。

checkPencil(){
    this.setState((prevState) => {
        return {
            pencil: !prevState.pencil
        };
    }, () => {
        this.props.updateItem(this.state)
    });
}

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android