【问题标题】:React - Add Class to Empty Input FieldsReact - 将类添加到空输入字段
【发布时间】:2019-11-01 13:16:09
【问题描述】:

我只想在输入为空时添加红色边框。我找不到在 React 中“添加类”的方法,所以我正在使用状态。现在代码将为所有输入添加红色边框,即使它有文本。

状态:

this.state = {
  inputBorderError: false,
};

HTML/JSX:

<label>Name</label>
<input className={
  this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />

<label>Email</label>
<input className={
  this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />

<label>Message</label>
<textarea className={
  this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />

CSS:

.form-input-fail {
  border: 1px solid red;
}

JS:

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

   for (var i = 0; i < inputFields.length; i++) {
      if (inputFields[i].value === '') {
        this.setState({
          inputBorderError: true,
        });
      }
    }

我在我的代码中看到了错误,因为它基本上是在找到空输入时将状态设置为 true。我想我可能会错误地处理这个问题,因为只有一个状态。是否有基于我的状态方法的解决方案,或者是否有其他解决方案?

【问题讨论】:

  • 嗨,Eric,试试我的解决方案中的代码框,我认为它应该涵盖所有基础。如果您有任何问题,请告诉我。
  • @ChristopherNgo 我正在考虑添加简单的电子邮件验证。对此有一个线程,可以使用您的专业知识:stackoverflow.com/questions/56676342/…

标签: javascript reactjs forms


【解决方案1】:

现在,您有一个影响所有输入的状态值,您应该考虑为每个input 设置一个状态值。此外,您的输入不受控制,因此更难记录和跟踪其值以进行错误处理。

给每个input 标记一个名称属性是一个很好的做法。更容易动态更新它们对应的状态值。

尝试以下操作,开始输入每个输入,然后删除您的文本:https://codesandbox.io/s/nervous-feynman-vfmh5

class App extends React.Component {
  state = {
    inputs: {
      name: "",
      email: "",
      message: ""
    },
    errors: {
      name: false,
      email: false,
      message: false
    }
  };

  handleOnChange = event => {
    this.setState({
      inputs: {
        ...this.state.inputs,
        [event.target.name]: event.target.value
      },
      errors: {
        ...this.state.errors,
        [event.target.name]: false
      }
    });
  };

  handleOnBlur = event => {
    const { inputs } = this.state;
    if (inputs[event.target.name].length === 0) {
      this.setState({
        errors: {
          ...this.state.errors,
          [event.target.name]: true
        }
      });
    }
  };

  handleOnSubmit = event => {
    event.preventDefault();
    const { inputs, errors } = this.state;
    //create new errors object
    let newErrorsObj = Object.entries(inputs)
      .filter(([key, value]) => {
        return value.length === 0;
      })
      .reduce((obj, [key, value]) => {
        if (value.length === 0) {
          obj[key] = true;
        } else {
          obj[key] = false;
        }
        return obj;
      }, {});

    if (Object.keys(newErrorsObj).length > 0) {
      this.setState({
        errors: newErrorsObj
      });
    }
  };

  render() {
    const { inputs, errors } = this.state;
    return (
      <div>
        <form onSubmit={this.handleOnSubmit}>
          <label>Name</label>
          <input
            className={
              errors.name ? "form-input form-input-fail" : "form-input"
            }
            name="name"
            value={inputs.name}
            onChange={this.handleOnChange}
            onBlur={this.handleOnBlur}
          />

          <label>Email</label>
          <input
            className={
              errors.email ? "form-input form-input-fail" : "form-input"
            }
            name="email"
            value={inputs.email}
            onChange={this.handleOnChange}
            onBlur={this.handleOnBlur}
          />

          <label>Message</label>
          <textarea
            className={
              errors.message ? "form-input form-input-fail" : "form-input"
            }
            name="message"
            value={inputs.message}
            onChange={this.handleOnChange}
            onBlur={this.handleOnBlur}
          />
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

【讨论】:

  • 三个点...代表什么?
  • 它被称为扩展运算符。它基本上将状态复制到另一个对象。
  • @EricNguyen 对此感到抱歉。是的,本质上它只是意味着您想从现有对象中获取现有的键值对并在新对象中使用它们。如果您有任何其他问题,请告诉我:)
  • @ChristopherNgo 为什么你有“const { inputs, errors } = this.state;”在渲染函数中?
  • @EricNguyen 被称为对象解构。您从对象中获取一个键并使用它来声明一个新变量,并为其分配原始键值对中的值。这基本上等同于const inputs = this.state.inputsconst errors = this.state.errors
【解决方案2】:

你说得对,只有一种状态。

您需要为每个输入存储一个单独的错误。一种方法是在状态上设置一个集合或数组,例如state = {errors: []},然后检查

<label>Name</label>
<input className={
  this.state.errors.includes('name') ? 'form-input form-input-fail' : 'form-input'
} />

<label>Email</label>
<input className={
  this.state.errors.includes('email') ? 'form-input form-input-fail' : 'form-input'
} />
} />

【讨论】:

    【解决方案3】:

    您应该跟踪状态中的输入值,而不是仅检查边界样式状态。

    根据您的代码,您可以将其重构为以下内容:

    // keep track of your input changes
    this.state = {
      inputs: {
        email: '',
        name: '',
        comment: '',
      },
      errors: {
        email: false,
        name: false,
        comment: false,
      }
    };
    
    // event handler for input changes
    
    handleChange = ({ target: { name, value } }) => {
        const inputChanges = {
           ...state.inputs,
           [name]: value
        }
    
        const inputErrors = {
           ...state.errors,
           [name]: value == ""
        }
    
        setState({
          inputs: inputChanges,
          errors: inputErrors,
        });
    }
    

    HTML/JSX

    // the name attribut for your input
    
    <label>Name</label>
    <input name="name" onChange={handleChange} className={
      this.errors.name == "" ? 'form-input form-input-fail' : 'form-input'
    } />
    
    <label>Email</label>
    <input name="email" onChange={handleChange} className={
      this.errors.email == "" ? 'form-input form-input-fail' : 'form-input'
    } />
    
    <label>Message</label>
    <textarea name="comment" onChange={handleChange} className={
      this.errors.comment == "" ? 'form-input form-input-fail' : 'form-input'
    } />
    

    如果你可能正在考虑用 CSS 和 js 实现它,你可以试试这篇文章matching-an-empty-input-box-using-css-and-js

    但是试着学习让你的组件可重用和干燥,因为那是享受 React 应用程序的开始。

    [修订]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 2018-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 1970-01-01
      相关资源
      最近更新 更多