javascript - 当 setState 没有立即运行时验证表单

标签 javascript reactjs forms

我在 React 中创建了表单,但在验证方面遇到了问题。

当我们点击(下面的示例和演示)提交表单而不填写输入字段时,我们应该会收到错误。这很好用。然而,同时我们也收到了成功消息,这意味着这个条件 (!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 为 true 来提交表单,请使用 setState 的回调来执行此操作。

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

关于javascript - 当 setState 没有立即运行时验证表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55939041/

相关文章:

javascript - 如何在显示元素时添加幻灯片动画

javascript - 按日期范围从和到过滤表列表

reactjs - 通过 API 调用设置表单的初始值

javascript - 当我调整窗口大小时,Svg 图标消失

ruby-on-rails - 使用其他模型的数据在 Rails 中填写表单时如何发送参数

javascript - Eclipse HTML5 项目 - JavaScript 代码辅助仅在某些情况下有效

css - Material UI - gutterBottom vs paragraph,区别是什么?

java - 使用 HTML 而不是 Swing 组件在 Java 桌面应用程序中创建表单是一个好习惯吗?

html - MaterializeCss 表单输入(提交)按钮

javascript - jQuery - 外部变量选择器/函数 - 变量求和