猿问

如果我使用传播运算符,为什么状态会更新为最新消息?

我有一个 React 应用程序,其中有一个包含一些字段和验证的表单。但是,验证没有像我期望的那样工作。代码如下:


state = {

  user: null,

  errors: {}

}


onSubmitHandler = e => {

  e.preventDefault();

  //Check if first Name is returned empty

  if (this.state.user.name.trim().length === 0) {

    this.setState({

      errors: {

        ...this.state.errors,

        name: "This field is required"

      }

    });

  }

  //Check if last name is returned empty

  if (this.state.user.surname.trim().length === 0) {

    this.setState({

      errors: {

        ...this.state.errors,

        surname: "This field is required"

      }

    });

    return;

  }

}

现在,当我不提供两个输入字段并将它们留空时,我希望我的状态显示两个错误消息,即errors: {name: "This field is required", surname: "This field is required"}


但我只收到最近的姓氏错误。所以我的结果显示像errors: {surname: "This field is required"}


为什么它会覆盖第一条错误消息?任何帮助,将不胜感激。输入字段的代码未显示,因为它们只是带有 onChange 事件处理程序的输入标签。


白猪掌柜的
浏览 152回答 2
2回答

拉风的咖菲猫

this.setState中的两个调用onSubmitHandler将一起进行批处理。来自React Docs - setState():将 setState() 视为请求而不是更新组件的即时命令。为了更好地感知性能,React 可能会延迟它,然后在一次传递中更新多个组件。React 不保证状态更改会立即应用。setState() 并不总是立即更新组件。它可能会分批更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 成为一个潜在的陷阱所以当你这样做时...this.state.errors,this.state.errors在两个if块中,指的是一个空对象。结果,您只能在状态中看到对象surname中的键。errors您可以通过复制this.state.errors对象来解决此问题,在复制的对象中添加键,然后将该复制的对象传递给this.setState.onSubmitHandler = e => {    e.preventDefault();        // clone the "errors" object    const errors = { ...this.state.errors };        //Check if first Name is returned empty    if(this.state.user.name.trim().length === 0) {         errors.name = "This field is required";    }                //Check if last name is returned empty    if(this.state.user.surname.trim().length === 0) {        errors.surname = "This field is required";    }    this.setState({ errors });}

泛舟湖上清波郎朗

这是因为第二次传播仍然使用 this.state.errors 的旧值,因为它还没有改变。在执行 onSubmitHandler 之后,两个 setStates 可能(在您的情况下:肯定是)稍后进行状态更新。将 setState 参数更改为自动使用最新状态的函数:onSubmitHandler = e => {  e.preventDefault();  //Check if first Name is returned empty  if (this.state.user.name.trim().length === 0) {    this.setState(state => ({      errors: {        ...state.errors,        name: "This field is required"      }    }));  }  //Check if last name is returned empty  if (this.state.user.surname.trim().length === 0) {    this.setState(state => ({      errors: {        ...state.errors,        surname: "This field is required"      }    }));    return;  }}
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答