【问题标题】:React - setState to True for All Empty Input Fields on SubmitReact - 在提交时将所有空输入字段设置为 True
【发布时间】:2019-06-23 23:14:18
【问题描述】:

如果输入字段为空,我想动态地将 setState 设置为 true。这样我就可以在每个输入字段的状态为真时通过 css 类为每个输入字段设置样式。

在我当前的代码中,它将运行循环并将最后一个空项设置为 true,即使所有输入都是空的。在我看来,我认为它应该将所有为空的内容设置为 true,但看起来循环只会识别最后一次迭代。

如何将所有为空的输入设置为 true?

HTML:

<form noValidate onSubmit={this.handleSubmit}>
  <label>Name</label>
  <input className="form-input" type="text" name="name">

  <label>Email</label>
  <input className="form-input" type="text" name="email">

  <label>Message</label>
  <input className="form-input" type="text" name="message">
</Form>

状态:

this.state = {
  errors: {
    name: false,
    email: false,
    message: false,
  },
};

JS:

handleSubmit = (e) => {

let inputFields = document.getElementsByClassName('form-input');

for (var i = 0; i < inputFields.length; i++) {
  if (inputFields[i].value === '') {

    let inputName = inputFields[i].name;

    this.setState({
      errors: {
        [inputName]: true,
      },
    });
  }
}

}

【问题讨论】:

    标签: javascript reactjs forms setstate


    【解决方案1】:

    问题是setState 仅将根键合并到状态中。 在您的情况下,您的状态是 { errors { ... } },通过执行 setState({ error: { ... } }),react 会替换状态内的整个错误对象。

    您可以在循环中制作errors 对象,并且只执行一次setState

    handleSubmit = (e) => {
      let inputFields = document.getElementsByClassName('form-input');
      let errors = {};
      for (var i = 0; i < inputFields.length; i++) {
        if (inputFields[i].value === '') {
          let inputName = inputFields[i].name;
          errors[inputName] = true;
        }
      }
      this.setState({errors});
    }
    

    这是更好的方法。但是,如果你也看看这种方法,它可能有助于理解 setState 的工作原理:

    您可以将密钥从 errors 移动到您的状态的根目录,因此 react 会将它们合并到状态中而不是替换它们。

    this.state = {
     nameError: false,
     emailError: false,
     messageError: false,
    };
    

    this.setState({
      [`${inputName}Error`]: true,
    });
    

    【讨论】:

    • 非常好的和干净的解决方案!澄清这一行:“errors[inputName] = true;” - 我知道它正在填充错误对象,但它是如何做到的?不理解语法,因为错误和 [inputName] 之间没有空格。谢谢
    • @EricNguyen 我不确定我是否正确理解了您的问题。当您拥有一个对象时,如果该属性以字符串形式存储在变量中,则可以使用方括号读取或写入属性。所以errors['name']=trueerror.name=true 是一样的。
    • 我建议阅读this
    • 谢谢@Amir 我现在明白了,是括号让我失望了,但我读了它。谢谢!
    【解决方案2】:

    要在保持组件当前状态结构的同时实现您的要求,请考虑对handleSubmit 进行以下更改:

    handleSubmit = (e) => {
        let inputFields = document.getElementsByClassName('form-input');
    
        /* Define errors object which will contain updated errors state based
        on form values */
        let errors = {};
    
        for (var i = 0; i < inputFields.length; i++) {
        if (inputFields[i].value === '') {
    
            let inputName = inputFields[i].name;
    
            /* Gather all error state into a single object */
            errors = { ...errors, [inputName]: true };
        }
        }
    
        /* Call setState once - this is more efficient and simplifies updating
        the nested errors object */
        this.setState((state) => {
    
            /* Replace nested error state with newly defined errors object */
            return { ...state, errors }
        });
    }
    

    这里我们利用errors 状态与表单相关的行为,因为它可以在handleSubmit 函数期间根据表单输入的值重新创建。

    首先,errors 对象在本地定义并根据表单输入的值组合。这个errors 对象根据输入值捕获表单的新错误状态。最后,setState 通过回调调用一次。这里将本地创建的errors对象指定为组件新嵌套的errors状态。

    【讨论】:

      猜你喜欢
      • 2014-04-02
      • 1970-01-01
      • 2021-08-10
      • 2017-02-08
      • 2015-06-04
      • 1970-01-01
      • 2019-07-05
      • 2012-04-10
      • 2022-07-09
      相关资源
      最近更新 更多