最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Simplest way to validate forms in react - Stack Overflow

programmeradmin0浏览0评论

I'm quite unsure how to do a form validation within react.

I want to display an error message on the current page saying. However, the password validation is ignored so their is no error that shows on the page.

Password must be at least characters

Maybe i'm not using conditional rendering right

SignUp.js (snippet for demonstration purpose)

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>

  );
 }

} 

I'm quite unsure how to do a form validation within react.

I want to display an error message on the current page saying. However, the password validation is ignored so their is no error that shows on the page.

Password must be at least characters

Maybe i'm not using conditional rendering right

SignUp.js (snippet for demonstration purpose)

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>

  );
 }

} 
Share Improve this question asked Jan 4, 2019 at 2:52 Eric ThomasEric Thomas 211 gold badge2 silver badges6 bronze badges 2
  • It looks like you need to change this.password > 6 to this.state.password.length < 6 – ic3b3rg Commented Jan 4, 2019 at 2:55
  • im getting TypeError: Cannot read property 'length' of undefined – Eric Thomas Commented Jan 4, 2019 at 2:58
Add a ment  | 

4 Answers 4

Reset to default 2

You should store the form data in your ponent's state. For example, have this.state.email instead of this.email. When data that is stored in a ponent's state is updated, a rerender is triggered. However, rerenders are not triggered for updates to plain class variables. You also directly manipulate the state when you set the errors. Instead you should use the setState method docs.

The reason you do not see your error shown on the page is because your page is not properly rerendering due to changes in the form.

Note it is also a good idea to wrap your form data variables in a formData object within state for organization. This helps keep the form's data separate from the rest of the ponent's state (e.g. keeps form values separate from your errors variable) and allows the form data to be passed around more easily, for example during form submission.

Here is an example of how you can reorganize things:

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 parison to _less_ than
    this.setState({ // update errors using setState -- never directly modify a ponent'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 ponent 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>

  );
 }

} 

Note: If your form has checkbox inputs, the shown handleChange method will not work as desired for those fields since the checked property of a checkbox input should be used instead of the value property. For simplicity, I've only included the non-checkbox case, but here is a full version of handleChange:

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

This example isn't using the ponent state to manage the Password and Email fields.

By having them as controlled input fields you can then validate them on change and conditionally render as error message (which doesn't need to be held in state)

eg. if you wanted to show an error is the password is too short:

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

Maybe check out https://github./jaredpalmer/formik and look at some examples.

I think your code to show error show use state

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

And in submit form you should update your state

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

})
  } else {
this.setState({errors: {}})
}

I have built custom hook for easy form validation. i think it's gonna make your life a lot easier es to form. you can leverage your html validation knowledge.

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

Website: 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>
  )
}
发布评论

评论列表(0)

  1. 暂无评论