在 setState 未立即运行时验证表单



我已经在react中创建了形式,我有验证的问题。

当我们单击(下面的示例和演示( Submit Form时,如果不填充输入字段,我们应该会遇到错误。这很好。但是,与此同时,我们还收到了成功消息,这意味着此条件(!this.state.firstNameError && !this.state.lastNameError)返回true,但不应该。它仅在第二次点击时就可以正常工作。

这是因为我猜setState没有立即更新。

我正在寻找一个很好的解决方案。

我可以用一种方法进行验证并提交,然后在错误的setState之后将success设置为true。但是我不想用一种方法持有这么多代码(我的真正形式要大得多(。什么是更好的解决方案?

一个简单的代码示例:

class App extends Component {
  state = {
    firstName: "",
    firstNameError: false,
    lastName: "",
    lastNameError: false,
    success: false
  };
  inputHandler = e => this.setState({ [e.target.name]: e.target.value });
  validateForm = () => {
    this.setState({
      firstNameError: false,
      lastNameError: false,
      success: false
    });
    if (!this.state.firstName) this.setState({ firstNameError: true });
    if (!this.state.lastName) this.setState({ lastNameError: true });
  };
  formSubmit = e => {
    e.preventDefault();
    this.validateForm();
    if (!this.state.firstNameError && !this.state.lastNameError) {
      this.setState({ success: true });
    }
  };
  render() {
    const { firstNameError, lastNameError, success } = this.state;
    return (
      <div className="container">
        <form onSubmit={this.formSubmit}>
          <div className="row">
            <label>First Name: </label>
            <input onChange={this.inputHandler} name="firstName" type="text" />
          </div>
          {firstNameError && <div className="error">Enter First Name</div>}
          <div className="row">
            <label>Last Name: </label>
            <input onChange={this.inputHandler} name="lastName" type="text" />
          </div>
          {lastNameError && <div className="error">Enter Last Name</div>}
          <div className="row">
            <button>Submit Form</button>
          </div>
          {success && <div className="success">Success</div>}
        </form>
      </div>
    );
  }
}

演示:https://codesandbox.io/s/30p90v6kp

validateForm中,找出每个字段的有效状态,然后使用该状态来确定表单整体是否有效,并且仅调用setState一次。

validateForm = () => {
  const firstNameError = !this.state.firstName;
  const lastNameError = !this.state.lastName;
  this.setState({
    firstNameError,
    lastNameError,
    success: !lastNameError && !firstNameError,
  });
};
formSubmit = e => {
  e.preventDefault();
  this.validateForm();
};

注意 - 取决于这是多么复杂以及您的表单实际提交方式,您可能会决定是否需要两个不同的功能。如果您正在等待this.state.success提交表格,请使用setState的回调。

this.setState(validatedState, newState => if (this.newState.success) submit() );

您可以通过验证名字来显示成功msg,并且姓氏值也与if(this.state.firstName !== "" && this.state.lastName !== "") { this.setState({ success: true }); }一样,它可能会为您提供帮助。我提供了下面的链接,请在此处找到https://codesandbox.io/s/q3ykw7wl3j

最新更新