Form validation in ReactJS

We already have seen how forms work in ReactJS. While working with forms, you also need to validate it. Let us have a look at an example of how to validate a form in ReactJS.


class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        fName: "",
        lName: "",
        email: "",
        password: "",
        mobile: "",
        submitted: false
      };
      this.handleSubmit = this.handleSubmit.bind(this);
      this.handleStateChange = this.handleStateChange.bind(this);
    }
    validateMobile(mobile){
      return /^\d{10}$/.test(mobile);
    }
    handleSubmit(e){
      e.preventDefault();
      this.setState({
        submitted: true
      });
      const {lName, fName, email, mobile, password} = this.state;
      if(fName && lName && email && mobile && this.validateMobile(mobile) && password){
        alert("Form is valid");
        // send data to server
      } else {
         alert("Form is invalid");
      }
    }
    handleStateChange(e){
      const {value, name} = e.target;
      this.setState({
        [name]: value
      });
    }
    render(){
        const { fName, lName, email, mobile, password, submitted } = this.state;
        return (
          <form onSubmit={this.handleSubmit}>
            <div>Login</div>
            <div className={submitted && !fName ? "error" : ""}>
              First Name: <input type="text" name="fName" value= {fName} onChange={this.handleStateChange}/>
              {
                submitted && !fName && 
                <div>Please enter First Name</div>
              }
            </div>
            <div className={submitted && !lName ? "error" : ""}>
              Last Name: <input type="text" name="lName" value= {lName} onChange={this.handleStateChange}/>
              {
                submitted && !lName && 
                <div>Please enter Last Name</div>
              }
            </div>
            <div className={submitted && !email ? "error" : ""}>
              Email: <input type="text" name="email" value= {email} onChange={this.handleStateChange}/>
              {
                submitted && !email && 
                <div>Please enter Email</div>
              }
            </div>
            <div className={submitted && ( !mobile || (mobile && !this.validateMobile(mobile))) ? "error" : ""}>
              Mobile Number: <input type="text" name="mobile" value= {mobile} onChange={this.handleStateChange}/>
              {
                submitted && !mobile && 
                <div>Please enter Mobile</div>
              }
              {
                submitted && mobile && !this.validateMobile(mobile) && 
                <div>Please enter valid Mobile</div>
              }
            </div>
            <div className={submitted && !password ? "error" : ""}>
              Password: <input type="password" name="password" value= {password} onChange={this.handleStateChange}/>
              {
                submitted && !password && 
                <div>Please enter Password</div>
              }
            </div>
            <div>
              <button type="submit">Submit</button>
            </div>
          </form>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);                                
                    

Open the above code in codepen.

In the above example, our strategy is very simple. When the user submits the form the first time, we check for validation. And we don't send data to the server until everything is validated. After that, we check every time the user makes some changes. So it will be validated whenever the user makes changes.

There are a few points that you should keep in mind while doing the above kind of validation.

  • Validation is checked whenever a user makes any change. (This may have some performance issue if your form is very very big but for 20 -30 fields, you should be fine.)
  • Validation is not done in a single place.

Please have a look at the below example.


class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        fName: "",
        lName: "",
        email: "",
        password: "",
        mobile: "",
        errors: {}
      };
      this.handleSubmit = this.handleSubmit.bind(this);
      this.handleStateChange = this.handleStateChange.bind(this);
      this.validateForm = this.validateForm.bind(this);
    }
    validateForm(){
      let {errors, fName, lName, email, password, mobile} = this.state;
      let isValid = true;
      if(!fName){
        errors["fName"] = "Please enter First Name";
        isValid &= false;
      } else {
        errors["fName"] = "";
        isValid &= true; 
      }
      if(!lName){
        errors["lName"] = "Please enter Last Name";
        isValid &= false;
      } else {
        errors["lName"] = "";
        isValid &= true;
      }
      if(!email){
        errors["email"] = "Please enter Email";
        isValid &= false;
      } else {
        errors["email"] = "";
        isValid &= true;
      }
      if(!password){
        errors["password"] = "Please enter Password";
        isValid &= false;
      } else {
        errors["password"] = "";
        isValid &= true;
      }
      if(!mobile){
        errors["mobile"] = "Please enter Mobile";
        isValid &= false;
      } else {
        if(mobile && /^\d{10}$/.test(mobile)){
          errors["mobile"] = "";
          isValid &= true;
        } else {
          errors["mobile"] = "Please enter valid mobile";
          isValid &= false;
        }
      }
      this.setState({
        errors
      })
      return isValid;
    }
    handleSubmit(e){
      e.preventDefault();
      if(this.validateForm()){
        alert("Form is valid");
        // send data to server
      } else {
         alert("Form is invalid");
      }
    }
    handleStateChange(e){
      const {value, name} = e.target;
      this.setState({
        [name]: value
      });
    }
    render(){
        const { fName, lName, email, mobile, password, errors } = this.state;
        return (
          <form onSubmit={this.handleSubmit}>
            <div>Login</div>
            <div>
              First Name: <input type="text" name="fName" value= {fName} onChange={this.handleStateChange}/>
              <div className="error">{errors["fName"]}</div>
            </div>
            <div>
              Last Name: <input type="text" name="lName" value= {lName} onChange={this.handleStateChange}/>
              <div className="error">{errors["lName"]}</div>
            </div>
            <div>
              Email: <input type="text" name="email" value= {email} onChange={this.handleStateChange}/>
              <div className="error">{errors["email"]}</div>
            </div>
            <div>
              Mobile Number: <input type="text" name="mobile" value= {mobile} onChange={this.handleStateChange}/>
              <div className="error">{errors["mobile"]}</div>
            </div>
            <div>
              Password: <input type="password" name="password" value= {password} onChange={this.handleStateChange}/>
              <div className="error">{errors["password"]}</div>
            </div>
            <div>
              <button type="submit">Submit</button>
            </div>
          </form>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);                          
                    

Open the above code in codepen.

In the above code, validation is done only in validateForm function. validateForm is called only when the form is submitted. So this is more simple and easy to implement.

Conclusion

In this section, we learned about validation in forms in ReactJS.
In the next section, you will learn about hooks in ReactJS.