【问题标题】:How to update state in react synchronously如何同步更新反应状态
【发布时间】:2018-10-10 07:05:43
【问题描述】:
onSave=()=>{
    if (this.state.intialValue<=0) {
        this.setState({errorIntialValue: true})
      }
      else
      {
      this.setState({errorIntialValue: false})
      }
      if (this.state.age>=25|| this.state.age<=-1) {
        this.setState({errorAge: true})
      }
      else{
        this.setState({errorAge: false})
      }
      if (this.state.rollNo<0) {
        this.setState({errorRollno: true})
      }
      else{
        this.setState({errorRollno: false})
      }
       if(!(this.state.errorIntialValue|| this.state.errorAge ||errorRollno)){    //have to 
                                                                    enter only if no error
    let newData={
            intialValue:this.state.intialValue,
            age:this.state.age,
            rollNo:this.state.rollNo
    }
    this.props.updateData(newData)
}

我有一个 onClick 事件 onSave。如果表单中存在错误,我将它们的状态设置为 true。由于 SetState 是异步的,因此该值不会更新为其状态,并且在到达 if(!(this.state.errorIntialValue || this.state.errorAge || errorRollno)) 时始终未定义并且它返回 false。 if 块中的代码永远不会被执行。 我找不到合适的方法来实现这一点。我该怎么做?

【问题讨论】:

  • 每次更改都不需要调用 setState,而是可以在更新的对象中设置值,最后调用 setState 一次
  • 看来你最好使用setState的功能版本和回调来实现这个功能
  • @BoyWithSilverWings 实际上我们也可以将回调与 setState() 的“对象”版本一起使用
  • @skyboyer 功能版本,因为 OP 使用状态进行比较。回调用于不同的用例
  • @BoyWithSilverWings 同意你的看法。即使onSave() 有一天看起来像点击处理程序,它也可以在.setState 之后以编程方式调用,并且事情会不同步

标签: reactjs axios setstate


【解决方案1】:

可以按照this answer 中的说明使用unstable_batchedUpdates 来同步状态更新:

// this.state.foo === 0 here

ReactDOM.unstable_batchedUpdates(() => {
    this.setState({ foo: this.state.foo + 1});
});

// this.state.foo === 1 here

这个方法在这里不适用,需要就说明有问题。

The documentation 建议如果setState 状态依赖于先前的状态,则使用更新函数,如果评估的代码依赖于先前设置的状态,则使用回调函数:

setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 是一个潜在的陷阱。相反,使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),它们都保证在应用更新后触发。如果您需要根据之前的状态设置状态,请阅读下面的 updater 参数。

从代码中不清楚为什么临时值(errorIntialValueerrorAgeerrorRollno)应该存储在组件状态中。它们可能不应该而且应该只更新一次,例如:

if (errorIntialValue || errorAge || errorRollno) {
  // update the state with errors
} else {
  // update the state with data
}

【讨论】:

  • 我猜它被存储到状态以突出显示错误/显示消息
【解决方案2】:

正如@BoyWithSilverWings 指出的那样,最好使用setState 的功能版本来确保我们对稳定状态进行检查。否则,当您以编程方式调用 this.onSave() 时,您可能会在旧版本的状态上进行操作。

考虑到这一点,我们使用回调函数作为@estus 提供的第二个参数。

onSave=()=>{
    this.setState(currentState = > {
        errorIntialValue: currentState.intialValue<=0,
        errorAge: currentState.age>=25|| currentState.age<=-1,
        errorRollno: currentState.rollNo<0
    }, ({errorIntialValue, errorAge, errorRollno}) => {
       if([errorIntialValue, errorAge, errorRollno].some(isInvalid=> isInvalid)){    
          let newData={
               intialValue:this.state.intialValue,
               age:this.state.age,
               rollNo:this.state.rollNo
          }
          this.props.updateData(newData)
       } 
    });

【讨论】:

    猜你喜欢
    • 2021-03-21
    • 2017-07-15
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 2022-01-23
    • 2018-03-28
    相关资源
    最近更新 更多