【问题标题】:Simplest way to validate forms in react在反应中验证表单的最简单方法
【发布时间】:2019-05-30 15:33:53
【问题描述】:

我很不确定如何在 react 中进行表单验证。

我想在当前页面上显示一条错误消息。但是,密码验证将被忽略,因此它们不会在页面上显示错误。

密码必须至少为字符

也许我没有使用conditional rendering

SignUp.js(用于演示目的的 sn-p)

constructor(props){
 super(props);

 this.state ={
  errors: {},
}

handleSubmit(event) {
  event.preventDefault();

  const email = this.email.value;
  const password = this.password.value;

  if(password.length > 6){
    this.state.errors.password= "Password must be at least 6 characters";
  }
  const creds = {email, password}

  if(creds){
    this.props.signUp(creds);
    this.props.history.push('/');

  }
}

render() {
 return (
  <div className="container">
    <div className="row">
      <div className="col-md-6">
        <h1>Sign Up</h1>
        <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>

            <input
              name="email"
              type="email"          
              className="form-control"
              id="email"
              ref={(input) => this.email = input}
              aria-describedby="emailHelp"
              placeholder="Enter email" />
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            {this.password > 6 &&
               //display an error here
              <h2>{this.state.errors.password}</h2>
            }
            <input
              name="password"
              type="password"
              ref={(input) => this.password = input}
              value={this.state.password}
              className="form-control"
              id="password"    
              placeholder="Password" />

          </div>



          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
      </div>

    </div>
  </div>

  );
 }

} 

【问题讨论】:

  • 看来你需要把this.password &gt; 6改成this.state.password.length &lt; 6
  • 我得到TypeError: Cannot read property 'length' of undefined

标签: javascript reactjs redux


【解决方案1】:

您应该将表单数据存储在组件的状态中。例如,使用 this.state.email 而不是 this.email。当存储在组件状态中的数据更新时,会触发重新渲染。但是,对于普通类变量的更新不会触发重新渲染。您还可以在设置errors 时直接操作状态。相反,您应该使用setState 方法docs

您在页面上看不到错误的原因是由于表单更改导致您的页面未正确重新呈现。

请注意,将表单数据变量包装在状态中的formData 对象中以进行组织也是一个好主意。这有助于将表单数据与组件的其他状态分开(例如,将表单值与错误变量分开)并允许更轻松地传递表单数据,例如在表单提交期间。

以下是如何重组事物的示例:

constructor(props){
 super(props);

 this.state = {
  formData: { // set up default form values
    email: "",
    password: "",
  },
  errors: {},
}

handleChange = event => {
  const { formData } = this.state;

  this.setState({
    formData: {
      ...formData, // leave other values unchanged
      [event.target.name]: event.target.value, // update the changed value
    }
  });
}

handleSubmit(event) {
  event.preventDefault();

  const { formData, errors } = this.state;
  const { email, password } = formData;

  if (password.length < 6) { // changed comparison to _less_ than
    this.setState({ // update errors using setState -- never directly modify a component's state
      errors: {
        ...errors,
        password: "Password must be at least 6 characters",
      }
    });
  }

  const creds = {email, password}

  if (creds.email && creds.password) { // objects are never falsey, so we need to check each field directly
    this.props.signUp(creds);
    this.props.history.push('/');

  }
}

render() {
 return (
  <div className="container">
    <div className="row">
      <div className="col-md-6">
        <h1>Sign Up</h1>
        <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>

            <input
              name="email"
              type="email"          
              className="form-control"
              id="email"
              value={ this.state.formData.email } {/* control component by storing value in state and updating state when the input changes */}
              onChange={ this.handleChange }
              aria-describedby="emailHelp"
              placeholder="Enter email" />
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            {this.state.errors.password &&
               //display an error here
              <h2>{this.state.errors.password}</h2>
            }
            <input
              name="password"
              type="password"
              value={ this.state.formData.password }
              onChange={ this.handleChange }
              className="form-control"
              id="password"    
              placeholder="Password" />

          </div>



          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
      </div>

    </div>
  </div>

  );
 }

} 

注意:如果您的表单具有复选框输入,则显示的handleChange 方法将无法按需要对这些字段起作用,因为应使用复选框输入的checked 属性而不是value 属性。为简单起见,我只包括了非复选框的情况,但这里是handleChange的完整版:

handleChange = event => {
    const { formData } = this.state;
    const { name, type, value, checked } = event.target;
    this.setState({
        formData: {
            ...formData,
            [name]: type === "checkbox" ? checked : value,
        }
    })
}

【讨论】:

  • 只有这个,{this.state.formData.password.length &lt; 6 &amp;&amp; //display an error here &lt;h2&gt;{this.state.errors.password}&lt;/h2&gt; } 不显示任何内容
  • 但它似乎想展示它自己,它看起来是隐形的。我可以看到 div 稍微向下移动,以便为错误腾出空间。但没有出现错误。
  • @EricThomas 可能是 CSS 问题,如果您 disable CSS 或打开浏览器的开发人员工具,您能看到消息吗? (我还更新了该部分,因为检查密码长度是重复的逻辑,只需检查密码是否存在错误就足够了)
  • @HenryWoody 问题:我不明白为什么if (creds) { ... } 会按预期工作。在这个 JSBin 中,即使 emailpassword 为空白,它也可以工作:jsbin.com/zelipad/edit?js,console。请说清楚。谢谢!
  • @thanks_in_advance 你是对的。此答案中的代码从问题中的代码开始,我只编辑了特别询问的部分。但是,正如您所指出的,if (creds) 行基本上是无用的,因为即使是空对象在 JS 中也是真实的。感谢您的评论,我现在将进行一些修改。
【解决方案2】:

我已经构建了自定义钩子以方便表单验证。我认为这会让你的生活变得更容易。您可以利用您的 html 验证知识。

Github:https://github.com/bluebill1049/react-hook-form

网址:http://react-hook-form.now.sh

import React from 'react'
import useForm from 'react-hook-form'

function App() {
  const { register, handleSubmit, errors } = useForm() // initialise the hook
  const onSubmit = (data) => { console.log(data) } // callback when validation pass

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstname" ref={register} /> {/* register an input */}

      <input name="lastname" ref={register({ required: true })} /> {/* apply required validation */}
      {errors.lastname && 'Last name is required.'} {/* error message */}

      <input name="age" ref={register({ pattern: /\d+/ })} /> {/* apply a Refex validation */}
      {errors.age && 'Please enter number for age.'} {/* error message */}

      <input type="submit" />
    </form>
  )
}

【讨论】:

    【解决方案3】:

    我认为你的代码显示错误显示使用状态

    {this.state.errors.password &&
               //display an error here
              <h2>{this.state.errors.password}</h2>
            }
    

    在提交表单中你应该更新你的状态

    if(password.length > 6){
    this.setState({ errors: { password: "Password must be at least 6 characters"} 
    
    })
      } else {
    this.setState({errors: {}})
    }
    

    【讨论】:

      【解决方案4】:

      此示例未使用组件状态来管理密码和电子邮件字段。

      通过将它们作为受控输入字段,您可以在更改时验证它们并有条件地呈现为错误消息(不需要保持状态)

      例如。如果你想显示错误是密码太短:

      { this.state.password.length < 5 && <p>Password too short</p> }

      也许看看https://github.com/jaredpalmer/formik 并看一些例子。

      【讨论】:

      • 我收到此错误TypeError: Cannot read property 'length' of undefined
      猜你喜欢
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 2020-05-15
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多