React Form Validation : Custom Validation in React Forms

React Form Validation : Custom Validation in React Forms

Overview

In modern web development, form validation is very important. Forms are a key way for users to interact with a website — like signing up, logging in, or entering data. To make sure the information users enter is correct and useful, we use validation. It checks the user’s input based on certain rules before sending the data. This helps make sure the data is accurate, complete, and in the right format, which is important for any application to work properly and reliably.

React Form Validation

Why Form Validation Matters in Your React Applications

In React applications, form validation is key to creating smooth and secure user experiences. Whether you’re using plain JavaScript, React Hook Form, or Formik, validating input fields like an email address ensures users submit correct data. With tools like handleSubmit, handleChange, and validation rules, you can easily check for errors, mark fields as invalid, and guide users to fix them.

React libraries help manage form state, making it easier to handle complex validations and give real-time feedback. Showing a clear validation error helps users correct mistakes before submission, improving data quality. Also, validation protects your app from bad or harmful inputs. Whether you’re building a form in HTML or using props in a React form, strong validation using a schema or custom logic is a must-have in modern web development.

Types of Form Validation in React

  • Required Fields: Ensures that important fields (like name, email, etc.) are not left empty. In libraries like React Hook Form or Formik, you can add a required rule to enforce this.
  • Data Format Validation: Checks if the input matches a specific format — like a valid email address or date. This often uses regex patterns or schema validation (e.g., using Yup).
  • Length Validation: Ensures the input has a minimum or maximum number of characters. Useful for usernames, passwords, etc.
  • Numeric Value Validation: Ensures only numbers are entered — great for age, phone numbers, or price fields. You can also set value ranges.
  • Pattern Matching: Uses regular expressions (regex) to validate complex formats, like strong passwords or postal codes.
  • Custom Validation: Lets you write your own logic to check a field — for example, checking if a username already exists or if two passwords match. In React, this can be done using functions passed to the form’s validate or resolver.

Steps to Implement Form Validation in React

Step 1: Setup Initial State

Create state variables using useState() to store form data and errors.

 

const [formData, setFormData] = useState({...});

const [error, setError] = useState({...});

Step 2: Handle Input Changes

Update the state as the user types using a handleChange function.


const handleChange = (e) => {

  const { name, value } = e.target;

  setFormData((prev) => ({ ...prev, [name]: value }));

};

Step 3: Validate Inputs Before Submission

Create a isValidate function to check required fields, email format, number format, etc.


const isValidate = () => {
  const errors = {};
  let isValid = true;

  if (!formData.firstName) {
    errors.firstName = "First Name is required";
    isValid = false;
  }

  // Add checks for all other fields similarly...

  setError(errors);
  return isValid;
};

 Step 4: Handle Form Submission

Prevent default form behavior, validate fields, then make an API request.


const handleSubmit = async (e) => {
  e.preventDefault();

  if (!(await isValidate())) return;

  try {
    const response = await axios.post(apiUrl, formData);
    setError({});
  } catch (error) {
    // Handle backend validation errors
  }
};

Step 5: Display Error Messages

Show validation messages under the respective fields using conditional rendering.


{ errors.firstName && 
  <span className="error-message">
    {errors.firstName}
  </span> 
}

Full React Code: React Form Validation Example

Here’s the complete code combining all the steps:


import React, { useState } from "react";
import axios from "axios";

function App() {
  const [formData, setFormData] = useState({
    firstName: "",
    lastName: "",
    email: "",
    contactNumber: "",
    address: "",
    city: "",
    state: "",
    country: "",
  });

  const [error, setError] = useState({});

  const isValidate = () => {
    const errors = {};
    let isValid = true;

    if (!formData.firstName) {
      errors.firstName = "First Name is required";
      isValid = false;
    }

    if (!formData.lastName) {
      errors.lastName = "Last Name is required";
      isValid = false;
    }

    if (!formData.email) {
      errors.email = "Email is required";
      isValid = false;
    } else if (
      !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(formData.email)
    ) {
      errors.email = "Invalid email address";
      isValid = false;
    }

    if (!formData.contactNumber) {
      errors.contactNumber = "Contact number is required";
      isValid = false;
    } else if (!/^[0-9]{10}$/.test(formData.contactNumber)) {
      errors.contactNumber = "Invalid Contact number";
      isValid = false;
    }

    if (!formData.address) {
      errors.address = "Address is required";
      isValid = false;
    }

    if (!formData.city) {
      errors.city = "City is required";
      isValid = false;
    }

    if (!formData.state) {
      errors.state = "State is required";
      isValid = false;
    }

    if (!formData.country) {
      errors.country = "Country is required";
      isValid = false;
    }

    setError(errors);
    return isValid;
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData((prevFormData) => ({ ...prevFormData, [name]: value }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    if (!(await isValidate())) return;

    try {
      const response = await axios.post("http://localhost:8082/saveUserData", formData);
      console.log(response);
      setError({});
    } catch (error) {
      console.log("API Error:", error);

      if (error.response && error.response.status === 400) {
        const apiErrors = {};
        error.response.data.forEach((err) => {
          apiErrors[err.field] = err.defaultMessage;
        });
        setError(apiErrors);
      } else {
        alert("Something went wrong");
      }
    }
  };

  return (
    <div className="App">
      <h2>Form Handling</h2>
      <form onSubmit={handleSubmit} className="form-container">
        {/* First Row */}
        <div className="form-group-container">
          <div className="form-group">
            <label>First Name</label>
            <input
              type="text"
              name="firstName"
              value={formData.firstName}
              onChange={handleChange}
            />
            {error.firstName && <span className="error-message">{error.firstName}</span>}
          </div>
          <div className="form-group">
            <label>Last Name</label>
            <input
              type="text"
              name="lastName"
              value={formData.lastName}
              onChange={handleChange}
            />
            {error.lastName && <span className="error-message">{error.lastName}</span>}
          </div>
        </div>

        {/* Second Row */}
        <div className="form-group-container">
          <div className="form-group">
            <label>Email</label>
            <input
              type="email"
              name="email"
              value={formData.email}
              onChange={handleChange}
            />
            {error.email && <span className="error-message">{error.email}</span>}
          </div>
          <div className="form-group">
            <label>Contact Number</label>
            <input
              type="tel"
              name="contactNumber"
              value={formData.contactNumber}
              onChange={handleChange}
            />
            {error.contactNumber && <span className="error-message">{error.contactNumber}</span>}
          </div>
        </div>

        {/* Third Row */}
        <div className="form-group-container">
          <div className="form-group">
            <label>Address</label>
            <input
              type="text"
              name="address"
              value={formData.address}
              onChange={handleChange}
            />
            {error.address && <span className="error-message">{error.address}</span>}
          </div>
          <div className="form-group">
            <label>City</label>
            <input
              type="text"
              name="city"
              value={formData.city}
              onChange={handleChange}
            />
            {error.city && <span className="error-message">{error.city}</span>}
          </div>
        </div>

        {/* Fourth Row */}
        <div className="form-group-container">
          <div className="form-group">
            <label>State</label>
            <input
              type="text"
              name="state"
              value={formData.state}
              onChange={handleChange}
            />
            {error.state && <span className="error-message">{error.state}</span>}
          </div>
          <div className="form-group">
            <label>Country</label>
            <input
              type="text"
              name="country"
              value={formData.country}
              onChange={handleChange}
            />
            {error.country && <span className="error-message">{error.country}</span>}
          </div>
        </div>

        {/* Submit Button */}
        <div className="submit-div">
          <button type="submit" className="submit-button">Submit</button>
        </div>
      </form>
    </div>
  );
}

export default App;

Validation Libraries in React – Get Started

When building forms in React, form handling and field validation are crucial for ensuring a good user experience and data integrity. Whether you’re developing in React, React Native, or using TypeScript, choosing the right validation library can help streamline development and reduce boilerplate code.

Here are the most popular validation libraries:

1. Yup – JavaScript Schema Builder

  • Yop is a powerful, expressive, and flexible validation library used with React and React Native.
  • You define a schema that describes your form structure and rules.
  • Best used with react-hook-form to easily integrate validation.

2. react-hook-form – Minimal and Performant

  • It is lightweight which is built specifically for React
  • Highly performant – reduces re-renders compared to traditional form handling with useState.
  • Great for beginners as well as advanced devs looking to build cleaner forms

3.  Redux Form – For State Management Lovers

  • Great when your app already uses Redux for state management.
  • Allows centralized control of the entire form using a state management library.
  • Can be overkill for small forms, but beneficial for enterprise-level applications.

4.  Formik – Battle-Tested & Community-Approved

  • It is Powerful and customizable which works well for complex forms in React.

Best Practices for React Form Validation

Whether you’re using React, React Router, or even frameworks like Angular, these best practices can help apply validation effectively and keep your UI clean and responsive.

1. Avoid Unnecessary Re-Renders

  • User react-hook-form instant of using useState for each field.
  • Minimize performance issues by using controlled components only when necessary.

2. Use Schema-Based Validation

  • Using Yup or Zod helps define all your field validation in one place.
  • Cleaner code, easier to maintain and reuse across components.

3. Componentize Your Form

  • Break the form into reusable React components for each field or group of fields.
  • Makes the UI more modular and easier to test or maintain.

4.  Use UI Libraries like Bootstrap

  • Libraries like Bootstrap, Material-UI, or Chakra UI help style your forms quickly.
  • Combine them with formstate and validation feedback to improve user experience..

5. Handle Entire Form as One Unit

  • Avoid scattered validation logic.
  • Use useForm from react-hook-form or a single validation schema to validate the entire form in one go.

Conclusion

Form validation in React is a critical skill for every React developer. Whether you’re just getting started or building enterprise-level apps, using the right combination of tools and patterns can streamline your development, improve performance, and ensure your forms are clean, usable, and effective.

Youtube Video –

Explore our more articles

Introduction to React Form Validation

In React In modern web development, form validation is very important. Forms are a key way for users to interact with a website — like signing up, logging in, or entering data. To make sure the information users enter is correct and useful, we use validation. It checks the user’s input based on certain rules before sending the data. This helps make sure the data is accurate, complete, and in the right format, which is important for any application to work properly and reliably.
 .

Why Form Validation Matters in Your React Applications?

In React applications, form validation is key to creating smooth and secure user experiences. Whether you’re using plain JavaScript, React Hook Form, or Formik, validating input fields like an email address ensures users submit correct data. With tools like handleSubmit, handleChange, and validation rules, you can easily check for errors, mark fields as invalid, and guide users to fix them.

React libraries help manage form state, making it easier to handle complex validations and give real-time feedback. Showing a clear validation error helps users correct mistakes before submission, improving data quality. Also, validation protects your app from bad or harmful inputs. Whether you’re building a form in HTML or using props in a React form, strong validation using a schema or custom logic is a must-have in modern web development.

What are the types of Form Validation in React

Required Fields: Ensures that important fields (like name, email, etc.) are not left empty. In libraries like React Hook Form or Formik, you can add a required rule to enforce this.
Data Format Validation: Checks if the input matches a specific format — like a valid email address or date. This often uses regex patterns or schema validation (e.g., using Yup).
Length Validation: Ensures the input has a minimum or maximum number of characters. Useful for usernames, passwords, etc.
Numeric Value Validation: Ensures only numbers are entered — great for age, phone numbers, or price fields. You can also set value ranges.
Pattern Matching: Uses regular expressions (regex) to validate complex formats, like strong passwords or postal codes.
Custom Validation: Lets you write your own logic to check a field — for example, checking if a username already exists or if two passwords match. In React, this can be done using functions passed to the form’s validate or resolver.

Steps to Implement Form Validation in React

Step 1: Setup Initial State
Step 2: Handle Input Changes
Step 3: Validate Inputs Before Submission
Step 4: Handle Form Submission
Step 5: Display Error Messages

What are the Validation Libraries in React ?

When building forms in React, form handling and field validation are crucial for ensuring a good user experience and data integrity. Whether you’re developing in React, React Native, or using TypeScript, choosing the right validation library can help streamline development and reduce boilerplate code.

What is the Best Practices for React Form Validation ?

Whether you’re using React, React Router, or even frameworks like Angular, these best practices can help apply validation effectively and keep your UI clean and responsive.

1. Avoid Unnecessary Re-Renders
2. Use Schema-Based Validation
3. Componentize Your Form
4.  Use UI Libraries like Bootstrap
5. Handle Entire Form as One Unit

1 thought on “React Form Validation : Custom Validation in React Forms”

Leave a Comment