当setState不立即运行时验证表单

时间:2019-05-01 15:55:52

标签: javascript reactjs forms

我已经在React中创建表单,但是验证存在问题。

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

发生这种情况是因为我猜setState不会立即更新。

我正在寻找解决此问题的好方法。

我可以用一种方法进行验证和提交,并在发生错误success之后的回调中将true设置为setState。但是我不想在一个方法中保存太多代码(我的形式实际上更大)。有什么更好的解决方案?

一个简单的代码示例:

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

2 个答案:

答案 0 :(得分:1)

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() );

答案 1 :(得分:0)

您可以通过验证名字和姓氏值来显示成功消息,就像if(this.state.firstName !== "" && this.state.lastName !== "") { this.setState({ success: true }); }一样,它可能会对您有所帮助。我提供了以下链接,请在这里https://codesandbox.io/s/q3ykw7wl3j