Clue Mediator

Form Validation in ReactJS

📅November 20, 2019

Form validation is one of the most important parts of the software application. Today we will show you how to create form and validate it in ReactJS.

Form Validation in ReactJS, Simple form validation using react js, React js form validation example, React js form validation step by step for beginners. Example of form validation in React.

Checkout more articles on React JS:

In this article, We will create a simple form with the use of different type of the fields and apply validation on each fields. Also we will handle the validation on Submit button click as well.

Way to implement: Form Validation in ReactJS

  1. Setup react application
  2. Install dependencies
  3. Understanding of form fields and validation
  4. Create form design
  5. Manage form values in states
  6. Implement Validation in Form
  7. Output

1. Setup react application

First we have to setup the react application to create form validation demo in React JS. If you don’t know how to create react application then follow below link.

Create React Application

2. Install dependencies

We will add two major dependencies in react application

  1. Add bootstrap for designing
  2. Install react-select package for dropdown

1. Add bootstrap for designing

We will add bootstrap cdn css link in project for designing purpose only. For that, you have to add the following style link in public/index.html file.

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>Form Validation in ReactJS - Clue Mediator</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

2. Install react-select package for dropdown

In this demo, We will use react-select package to display dropdown. In order to use react-select you have to run below command to install package.

npm i react-select

3. Understanding of form fields and validations

In this demo will cover all the type of fields and implement validation for each field. We can also consider it as signup form. Checkout the below list for better understanding.

| Field | HTML Element | Validations | | ---------------- | ----------------------- | ------------------------------------------------ | | Name | Input (type text) | required | | Email | Input (type text) | required, email | | Password | Input (type password) | required, compare it with Confirm Password field | | Confirm Password | Input (type password) | required, compare it with Password field | | Mobile | Input (type text) | required, number | | Gender | Input (type radio) | required | | Zip Code | Input (type text) | N/A | | Country | Dropdown (react-select) | required | | Language | Input (type checkbox) | required |

4. Create form design

Now we will create a simple design for signup page by the use of bootstrap classes. We will also display an asterisk (*) mark for mandatory fields and at last we will use “Submit” button to handle the form.

We have to define the two class variables to manage the list of Country and Language fields and those variable must be written in constructor or somewhere in static file.

 constructor() {
    super();
    this.countryList = [
      { value: "india", label: "India" },
      { value: "us", label: "US" },
      { value: "australia", label: "Australia" }
    ];
    this.languageList = [
      { value: "english", label: "English" },
      { value: "hindi", label: "Hindi" },
      { value: "spanish", label: "Spanish" },
      { value: "arabic", label: "Arabic" }
    ];
  }

Now your code should look like below.

App.js

import React, { Component } from 'react';
import ReactSelect from 'react-select';

class App extends Component {
  constructor() {
    super();
    this.countryList = [
      { value: "india", label: "India" },
      { value: "us", label: "US" },
      { value: "australia", label: "Australia" }
    ];
    this.languageList = [
      { value: "english", label: "English" },
      { value: "hindi", label: "Hindi" },
      { value: "spanish", label: "Spanish" },
      { value: "arabic", label: "Arabic" }
    ];
  }
  render() {
    return (
      <div className="signup-box">
        <p className="title">Sign up</p>
        <div className="row">
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Name:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="name"
              />
            </div>
            <div className="form-group">
              <label>
                Email:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="email"
              />
            </div>
            <div className="form-group">
              <label>
                Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="password"
              />
            </div>
            <div className="form-group">
              <label>
                Confirm Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="confirmPassword"
              />
            </div>
            <div className="form-group">
              <label className="mr-3">
                Language:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                {this.languageList.map((x, i) => {
                  return (
                    <label key={i} className="mr-2">
                      <input
                        type="checkbox"
                        name="language"
                        value={x.value}
                      /> {x.label}
                    </label>
                  );
                })}
              </div>
            </div>
          </div>
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Mobile:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="mobile"
              />
            </div>
            <div className="form-group">
              <label className="mr-3">
                Gender:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                <label className="mr-2">
                  <input
                    type="radio"
                    name="gender"
                    value="male"
                  /> Male
                </label>
                <label>
                  <input
                    type="radio"
                    name="gender"
                    value="female"
                  /> Female
                </label>
              </div>
            </div>
            <div className="form-group">
              <label>Zip Code:</label>
              <input
                className="form-control"
                type="text"
                name="zipCode"
              />
            </div>
            <div className="form-group">
              <label>
                Country:<span className="asterisk">*</span>
              </label>
              <ReactSelect
                name="country"
                options={this.countryList}
              />
            </div>
          </div>
        </div>

        <div className="form-group">
          <input
            type="button"
            className="btn btn-primary"
            value="Submit"
          />
        </div>
      </div>
    );
  }
}

export default App;

index.css

.signup-box{
  border: 1px solid #ddd;
  width: 700px;
  margin: 20px auto;
  padding: 20px;
  border-radius: 5px;
}
.title{
  font-weight: 600;
  margin-top:0;
}
.err {
  font-size: small;
  color: red;
}
.asterisk{
  font-size: small;
  color: red;
}

5. Manage form values in states

Now we will create state variable to manage all fields of the form. For that create state variable as “form” to store the value of the form in the form of an object.

  constructor() {
    super();
    this.state = {
      form: {
        name: "",
        email: "",
        mobile: "",
        password: "",
        confirmPassword: "",
        gender: null,
        language: [],
        country: null,
        zipCode: ""
      }
    };
    this.countryList = [
      { value: "india", label: "India" },
      { value: "us", label: "US" },
      { value: "australia", label: "Australia" }
    ];
    this.languageList = [
      { value: "english", label: "English" },
      { value: "hindi", label: "Hindi" },
      { value: "spanish", label: "Spanish" },
      { value: "arabic", label: "Arabic" }
    ];
  }

We need one method where we can handle the change event of the html elements. It will be used to store the changed value in state variable. It should look like below.

  handleChange = e => {
    const { name, value, checked } = e.target;
    const { form } = this.state;
    let formObj = {};
    if (name === "language") {
      // handle the change event of language field
      if (checked) {
        // push selected value in list
        formObj = { ...form };
        formObj[name].push(value);
      } else {
        // remove unchecked value from the list
        formObj = {
          ...form,
          [name]: form[name].filter(x => x !== value)
        };
      }
    } else {
      // handle change event except language field
      formObj = {
        ...form,
        [name]: value
      };
    }
    this.setState({ form: formObj });
  }

Now we will bind those variables with the HTML elements. We will bind two attributes (value & onChange) to make it working.

How to Handle Events in ReactJS

Your render method should look like below.

  render() {
    const { form } = this.state;
    return (
      <div className="signup-box">
        <p className="title">Sign up</p>
        <div className="row">
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Name:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="name"
                value={form.name}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Email:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="email"
                value={form.email}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="password"
                value={form.password}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Confirm Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="confirmPassword"
                value={form.confirmPassword}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label className="mr-3">
                Language:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                {this.languageList.map((x, i) => {
                  return (
                    <label key={i} className="mr-2">
                      <input
                        type="checkbox"
                        name="language"
                        value={x.value}
                        checked={form.language.includes(x.value)}
                        onChange={this.handleChange}
                      /> {x.label}
                    </label>
                  );
                })}
              </div>
            </div>
          </div>
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Mobile:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="mobile"
                value={form.mobile}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label className="mr-3">
                Gender:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                <label className="mr-2">
                  <input
                    type="radio"
                    name="gender"
                    value="male"
                    checked={form.gender === "male"}
                    onChange={this.handleChange}
                  /> Male
                </label>
                <label>
                  <input
                    type="radio"
                    name="gender"
                    value="female"
                    checked={form.gender === "female"}
                    onChange={this.handleChange}
                  /> Female
                </label>
              </div>
            </div>
            <div className="form-group">
              <label>Zip Code:</label>
              <input
                className="form-control"
                type="text"
                name="zipCode"
                value={form.zipCode}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Country:<span className="asterisk">*</span>
              </label>
              <ReactSelect
                name="country"
                options={this.countryList}
                value={this.countryList.find(x => x.value == form.country)}
                onChange={e =>
                  this.handleChange({
                    target: {
                      name: "country",
                      value: e.value
                    }
                  })
                }
              />
            </div>
          </div>
        </div>

        <div className="form-group">
          <input
            type="button"
            className="btn btn-primary"
            value="Submit"
          />
        </div>
      </div>
    );
  }

Now we have to strict the number type for “Mobile” field. For that we have to validate the input field on key press event.

  validateNumber = evt => {
    var theEvent = evt || window.event;

    // Handle paste
    if (theEvent.type === "paste") {
      key = theEvent.clipboardData.getData("text/plain");
    } else {
      // Handle key press
      var key = theEvent.keyCode || theEvent.which;
      key = String.fromCharCode(key);
    }
    var regex = /[0-9]|\./;
    if (!regex.test(key)) {
      theEvent.returnValue = false;
      if (theEvent.preventDefault) theEvent.preventDefault();
    }
  };
. . .
. . .
. . .
  <div className="form-group">
    <label>
      Mobile:<span className="asterisk">*</span>
    </label>
    <input
      className="form-control"
      type="text"
      name="mobile"
      value={form.mobile}
      onChange={this.handleChange}
      onKeyPress={this.validateNumber}
    />
  </div>
. . .
. . .

Now we have to handle the click event of the “Submit” button and write the console log of the form values.

  handleSubmit = () => {
    console.log(`Data: ${JSON.stringify(this.state.form)}`);
  };

. . .
. . .

  <div className="form-group">
    <input
      type="button"
      className="btn btn-primary"
      value="Submit"
      onClick={this.handleSubmit}
    />
  </div>
. . .
. . .

6. Implement Validation in Form

Now we will create function where we can validate the field based on the input value and return the validation message.

  validateField = (name, value, refValue) => {
    let errorMsg = null;
    switch (name) {
      case "name":
        if (!value) errorMsg = "Please enter Name.";
        break;
      case "email":
        if (!value) errorMsg = "Please enter Email.";
        else if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value))
          errorMsg = "Please enter valid Email.";
        break;
      case "mobile":
        if (!value) errorMsg = "Please enter Mobile.";
        break;
      case "country":
        if (!value) errorMsg = "Please select Country.";
        break;
      case "gender":
        if (!value) errorMsg = "Please select Gender.";
        break;
      case "password":
        // refValue is the value of Confirm Password field
        if (!value) errorMsg = "Please enter Password.";
        else if (refValue && value !== refValue)
          errorMsg = "Password and Confirm Password does not match.";
        break;
      case "confirmPassword":
        // refValue is the value of Password field
        if (!value) errorMsg = "Please enter Confirm Password.";
        else if (refValue && value !== refValue)
          errorMsg = "Password and Confirm Password does not match.";
        break;
      case "language":
        if (value.length === 0) errorMsg = "Please select Language.";
        break;
      default:
        break;
    }
    return errorMsg;
  };

Here we used refValue for Password and Confirm Password field to compare it with each other and based on it we are sending the appropriate message.

Below is the code where we define one more state variable as object to manage the error message.

  this.state = {
    form: {
      name: "",
      email: "",
      mobile: "",
      password: "",
      confirmPassword: "",
      gender: null,
      language: [],
      country: null,
      zipCode: ""
    },
    formErrors: {
      name: null,
      email: null,
      mobile: null,
      password: null,
      confirmPassword: null,
      gender: null,
      language: null,
      country: null
    }
  };

Now we have to slightly change the “handleChange” method to validate the value after the setState. Checkout the updated method below.

  handleChange = e => {
    const { name, value, checked } = e.target;
    const { form, formErrors } = this.state;
    let formObj = {};
    if (name === "language") {
      // handle the change event of language field
      if (checked) {
        // push selected value in list
        formObj = { ...form };
        formObj[name].push(value);
      } else {
        // remove unchecked value from the list
        formObj = {
          ...form,
          [name]: form[name].filter(x => x !== value)
        };
      }
    } else {
      // handle change event except language field
      formObj = {
        ...form,
        [name]: value
      };
    }
    this.setState({ form: formObj }, () => {
      if (!Object.keys(formErrors).includes(name)) return;
      let formErrorsObj = {};
      if (name === "password" || name === "confirmPassword") {
        let refValue = this.state.form[
          name === "password" ? "confirmPassword" : "password"
        ];
        const errorMsg = this.validateField(name, value, refValue);
        formErrorsObj = { ...formErrors, [name]: errorMsg };
        if (!errorMsg && refValue) {
          formErrorsObj.confirmPassword = null;
          formErrorsObj.password = null;
        }
      } else {
        const errorMsg = this.validateField(
          name,
          name === "language" ? this.state.form["language"] : value
        );
        formErrorsObj = { ...formErrors, [name]: errorMsg };
      }
      this.setState({ formErrors: formErrorsObj });
    });
  }

To display the error message, We need to update render method same as below.

  render() {
    const { form, formErrors } = this.state;
    return (
      <div className="signup-box">
        <p className="title">Sign up</p>
        <div className="row">
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Name:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="name"
                value={form.name}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.name && <span className="err">{formErrors.name}</span>}
            </div>
            <div className="form-group">
              <label>
                Email:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="email"
                value={form.email}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.email && <span className="err">{formErrors.email}</span>}
            </div>
            <div className="form-group">
              <label>
                Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="password"
                value={form.password}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.password && <span className="err">{formErrors.password}</span>}
            </div>
            <div className="form-group">
              <label>
                Confirm Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="confirmPassword"
                value={form.confirmPassword}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.confirmPassword && <span className="err">{formErrors.confirmPassword}</span>}
            </div>
            <div className="form-group">
              <label className="mr-3">
                Language:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                {this.languageList.map((x, i) => {
                  return (
                    <label key={i} className="mr-2">
                      <input
                        type="checkbox"
                        name="language"
                        value={x.value}
                        checked={form.language.includes(x.value)}
                        onChange={this.handleChange}
                      /> {x.label}
                    </label>
                  );
                })}
              </div>
              {formErrors.language && <span className="err">{formErrors.language}</span>}
            </div>
          </div>
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Mobile:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="mobile"
                value={form.mobile}
                onChange={this.handleChange}
                onBlur={this.handleChange}
                onKeyPress={this.validateNumber}
              />
              {formErrors.mobile && <span className="err">{formErrors.mobile}</span>}
            </div>
            <div className="form-group">
              <label className="mr-3">
                Gender:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                <label className="mr-2">
                  <input
                    type="radio"
                    name="gender"
                    value="male"
                    checked={form.gender === "male"}
                    onChange={this.handleChange}
                  /> Male
                </label>
                <label>
                  <input
                    type="radio"
                    name="gender"
                    value="female"
                    checked={form.gender === "female"}
                    onChange={this.handleChange}
                  /> Female
                </label>
              </div>
              {formErrors.gender && <span className="err">{formErrors.gender}</span>}
            </div>
            <div className="form-group">
              <label>Zip Code:</label>
              <input
                className="form-control"
                type="text"
                name="zipCode"
                value={form.zipCode}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Country:<span className="asterisk">*</span>
              </label>
              <ReactSelect
                name="country"
                options={this.countryList}
                value={this.countryList.find(x => x.value == form.country)}
                onChange={e =>
                  this.handleChange({
                    target: {
                      name: "country",
                      value: e.value
                    }
                  })
                }
              />
              {formErrors.country && <span className="err">{formErrors.country}</span>}
            </div>
          </div>
        </div>

        <div className="form-group">
          <input
            type="button"
            className="btn btn-primary"
            value="Submit"
            onClick={this.handleSubmit}
          />
        </div>
      </div>
    );
  }

Now at last we need to change the submit handler to validate the form before submitting it.

  validateForm = (form, formErrors, validateFunc) => {
    const errorObj = {};
    Object.keys(formErrors).map(x => {
      let refValue = null;
      if (x === "password" || x === "confirmPassword") {
        refValue = form[x === "password" ? "confirmPassword" : "password"];
      }
      const msg = validateFunc(x, form[x], refValue);
      if (msg) errorObj[x] = msg;
    });
    return errorObj;
  };

  handleSubmit = () => {
    const { form, formErrors } = this.state;
    const errorObj = this.validateForm(form, formErrors, this.validateField);
    if (Object.keys(errorObj).length != 0) {
      this.setState({ formErrors: { ...formErrors, ...errorObj } });
      return false;
    }
    console.log('Data: ', form);
  };

That’s it for form validation.

7. Output

After following each step your whole code of file should look like below.

App.js

import React, { Component } from 'react';
import ReactSelect from 'react-select';

class App extends Component {
  constructor() {
    super();
    this.state = {
      form: {
        name: "",
        email: "",
        mobile: "",
        password: "",
        confirmPassword: "",
        gender: null,
        language: [],
        country: null,
        zipCode: ""
      },
      formErrors: {
        name: null,
        email: null,
        mobile: null,
        password: null,
        confirmPassword: null,
        gender: null,
        language: null,
        country: null
      }
    };
    this.countryList = [
      { value: "india", label: "India" },
      { value: "us", label: "US" },
      { value: "australia", label: "Australia" }
    ];
    this.languageList = [
      { value: "english", label: "English" },
      { value: "hindi", label: "Hindi" },
      { value: "spanish", label: "Spanish" },
      { value: "arabic", label: "Arabic" }
    ];
  }

  validateNumber = evt => {
    var theEvent = evt || window.event;

    // Handle paste
    if (theEvent.type === "paste") {
      key = theEvent.clipboardData.getData("text/plain");
    } else {
      // Handle key press
      var key = theEvent.keyCode || theEvent.which;
      key = String.fromCharCode(key);
    }
    var regex = /[0-9]|\./;
    if (!regex.test(key)) {
      theEvent.returnValue = false;
      if (theEvent.preventDefault) theEvent.preventDefault();
    }
  };

  handleChange = e => {
    const { name, value, checked } = e.target;
    const { form, formErrors } = this.state;
    let formObj = {};
    if (name === "language") {
      // handle the change event of language field
      if (checked) {
        // push selected value in list
        formObj = { ...form };
        formObj[name].push(value);
      } else {
        // remove unchecked value from the list
        formObj = {
          ...form,
          [name]: form[name].filter(x => x !== value)
        };
      }
    } else {
      // handle change event except language field
      formObj = {
        ...form,
        [name]: value
      };
    }
    this.setState({ form: formObj }, () => {
      if (!Object.keys(formErrors).includes(name)) return;
      let formErrorsObj = {};
      if (name === "password" || name === "confirmPassword") {
        let refValue = this.state.form[
          name === "password" ? "confirmPassword" : "password"
        ];
        const errorMsg = this.validateField(name, value, refValue);
        formErrorsObj = { ...formErrors, [name]: errorMsg };
        if (!errorMsg && refValue) {
          formErrorsObj.confirmPassword = null;
          formErrorsObj.password = null;
        }
      } else {
        const errorMsg = this.validateField(
          name,
          name === "language" ? this.state.form["language"] : value
        );
        formErrorsObj = { ...formErrors, [name]: errorMsg };
      }
      this.setState({ formErrors: formErrorsObj });
    });
  }

  validateField = (name, value, refValue) => {
    let errorMsg = null;
    switch (name) {
      case "name":
        if (!value) errorMsg = "Please enter Name.";
        break;
      case "email":
        if (!value) errorMsg = "Please enter Email.";
        else if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value))
          errorMsg = "Please enter valid Email.";
        break;
      case "mobile":
        if (!value) errorMsg = "Please enter Mobile.";
        break;
      case "country":
        if (!value) errorMsg = "Please select Country.";
        break;
      case "gender":
        if (!value) errorMsg = "Please select Gender.";
        break;
      case "password":
        // refValue is the value of Confirm Password field
        if (!value) errorMsg = "Please enter Password.";
        else if (refValue && value !== refValue)
          errorMsg = "Password and Confirm Password does not match.";
        break;
      case "confirmPassword":
        // refValue is the value of Password field
        if (!value) errorMsg = "Please enter Confirm Password.";
        else if (refValue && value !== refValue)
          errorMsg = "Password and Confirm Password does not match.";
        break;
      case "language":
        if (value.length === 0) errorMsg = "Please select Language.";
        break;
      default:
        break;
    }
    return errorMsg;
  };

  validateForm = (form, formErrors, validateFunc) => {
    const errorObj = {};
    Object.keys(formErrors).map(x => {
      let refValue = null;
      if (x === "password" || x === "confirmPassword") {
        refValue = form[x === "password" ? "confirmPassword" : "password"];
      }
      const msg = validateFunc(x, form[x], refValue);
      if (msg) errorObj[x] = msg;
    });
    return errorObj;
  };

  handleSubmit = () => {
    const { form, formErrors } = this.state;
    const errorObj = this.validateForm(form, formErrors, this.validateField);
    if (Object.keys(errorObj).length !== 0) {
      this.setState({ formErrors: { ...formErrors, ...errorObj } });
      return false;
    }
    console.log('Data: ', form);
  };

  render() {
    const { form, formErrors } = this.state;
    return (
      <div className="signup-box">
        <p className="title">Sign up</p>
        <div className="row">
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Name:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="name"
                value={form.name}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.name && <span className="err">{formErrors.name}</span>}
            </div>
            <div className="form-group">
              <label>
                Email:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="email"
                value={form.email}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.email && <span className="err">{formErrors.email}</span>}
            </div>
            <div className="form-group">
              <label>
                Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="password"
                value={form.password}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.password && <span className="err">{formErrors.password}</span>}
            </div>
            <div className="form-group">
              <label>
                Confirm Password:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="password"
                name="confirmPassword"
                value={form.confirmPassword}
                onChange={this.handleChange}
                onBlur={this.handleChange}
              />
              {formErrors.confirmPassword && <span className="err">{formErrors.confirmPassword}</span>}
            </div>
            <div className="form-group">
              <label className="mr-3">
                Language:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                {this.languageList.map((x, i) => {
                  return (
                    <label key={i} className="mr-2">
                      <input
                        type="checkbox"
                        name="language"
                        value={x.value}
                        checked={form.language.includes(x.value)}
                        onChange={this.handleChange}
                      /> {x.label}
                    </label>
                  );
                })}
              </div>
              {formErrors.language && <span className="err">{formErrors.language}</span>}
            </div>
          </div>
          <div className="col-md-6">
            <div className="form-group">
              <label>
                Mobile:<span className="asterisk">*</span>
              </label>
              <input
                className="form-control"
                type="text"
                name="mobile"
                value={form.mobile}
                onChange={this.handleChange}
                onBlur={this.handleChange}
                onKeyPress={this.validateNumber}
              />
              {formErrors.mobile && <span className="err">{formErrors.mobile}</span>}
            </div>
            <div className="form-group">
              <label className="mr-3">
                Gender:<span className="asterisk">*</span>
              </label>
              <div className="form-control border-0 p-0 pt-1">
                <label className="mr-2">
                  <input
                    type="radio"
                    name="gender"
                    value="male"
                    checked={form.gender === "male"}
                    onChange={this.handleChange}
                  /> Male
                </label>
                <label>
                  <input
                    type="radio"
                    name="gender"
                    value="female"
                    checked={form.gender === "female"}
                    onChange={this.handleChange}
                  /> Female
                </label>
              </div>
              {formErrors.gender && <span className="err">{formErrors.gender}</span>}
            </div>
            <div className="form-group">
              <label>Zip Code:</label>
              <input
                className="form-control"
                type="text"
                name="zipCode"
                value={form.zipCode}
                onChange={this.handleChange}
              />
            </div>
            <div className="form-group">
              <label>
                Country:<span className="asterisk">*</span>
              </label>
              <ReactSelect
                name="country"
                options={this.countryList}
                value={this.countryList.find(x => x.value === form.country)}
                onChange={e =>
                  this.handleChange({
                    target: {
                      name: "country",
                      value: e.value
                    }
                  })
                }
              />
              {formErrors.country && <span className="err">{formErrors.country}</span>}
            </div>
          </div>
        </div>

        <div className="form-group">
          <input
            type="button"
            className="btn btn-primary"
            value="Submit"
            onClick={this.handleSubmit}
          />
        </div>
      </div>
    );
  }
}

export default App;

Output - Form Validation in ReactJS - Clue Mediator

Output - Form Validation in ReactJS - Clue Mediator

Demo & Source Code

Github Repository StackBlitz Project