Form Validation in React

Friday, June 13, 2025

Form validation is a process of verifying user inputs at the time of entering, thus preventing users from entering incorrect or inappropriate details. It ensures that the entered details comply with the expected format, constraints, and any other required logic.

We’ll discuss in this blog post form validation in React applications in detail. We’ll try to understand the significance of form validation in web applications, different form validation techniques, how React development companies implement it, prominent form validation React libraries, and some of the best practices to perform form validation.

1. Why Form Validation Matters?

Have you wondered why it is necessary to understand and implement so many form validation techniques and libraries? Why are there specific libraries for form creation and validation? Here are some fundamental reasons.

  • Data Accuracy: User data helps understand user interaction and expectations, so it’s important to ensure that the data collected is accurate and reliable.
  • Security: Forms contain personal user information therefore, data privacy is a must. Validation helps prevent hackers from exploiting vulnerabilities and protects the system from malicious inputs.
  • Data Integrity: Forms cannot accept duplicate or irrelevant data. Validation implements appropriate data integrity mechanisms to allow storage of only correct user input.

2. Form Validation Techniques

Below are some of the most commonly used form validation techniques in React.

2.1 Built-in HTML5 Validation Attributes

Form validation is one of the essential operations in a web development process. It helps users submit their data on the website in a suitable format. This article acts as a step-by-step guide to creating a simple registration form using native HTML5 validation features in React. 

Project Setup: Assuming that you are working in a React environment, let us start by creating a basic form using Vite.

Creating the Basic Form

Create a basic form layout and then define its behavior using the action and method attributes.






Explanation: 

  • action=”/submit”: Shows where the form will be submitted. 
  • method=”post”: Used to send data securely. 
  • type=”submit”: Triggers the action of form submission.

Required Field Validation

The input can’t be empty. So, HTML5 offers the required attribute.

Explanation: It is to ensure that the users don’t submit their forms without filling in the username.

Email Format Validation

Enforce the use of a valid email pattern through the type=”email” input.

Whenever the user applies an invalid email format, HTML will automatically reject it.

Password Length Validation

To ensure that the users set a secure password, set a minimum character length for it.

You can easily apply some additional rules or patterns to the password in the code. 

Numeric Range Validation

Utilize the min and max functions to restrict the number input.

This helps you impose an age limit in the forms for surveys or registration. 

Pattern Matching for Phone Numbers

The pattern attribute lets you apply custom regular expressions.

Regex Explained: \d{3}-\d{3}-\d{4}: matches a format like 123-456-7890.

URL Validation

Validate websites using type=”url”.

Uses built-in validation to catch missing protocols from the URL.

Output:

Integration Flow: 

  1. The user fills the form. 
  2. HTML5 validation runs for every filled input. 
  3. If any field is found with an invalid input, the browser blocks form submission. 
  4. If the inputs are found valid, the form is submitted to the/submit endpoint.

We have successfully placed some robust form validation in the React application using only native HTML5 attributes. You don’t need any help from external libraries, and hence it is easier to maintain, making it rather a lightweight approach. 

2.2 Manual Form Validation in React

Native HTML validation is certainly a convenient approach, but there are limitations to it. On the contrary, manual validation provides full control over how and when to validate the fields. This section explores the process of handling form validation manually using React.useState.

Define Form State and Error Handling

The state in the React app must store both values and error messages.

import { useState } from 'react';
interface FormData { 
userName: string;
email: string; password: string; age: number | string; phone: string;
}
type ErrorMessages = { [key: string]: string;
};
const [formData, setFormData] = useState({ userName: '',
email: '',
password: '',
age: '',
phone: '',
});
const [formError, setFormError] = useState({});

The form data and validation errors are handled separately, so it becomes necessary to separate them. 

Handle Input Change

Update the state and trigger validation for every input change.

const handleOnChange = (event: React.ChangeEvent) => { const { name, value } = event.target;
setFormData(prevFormData => {
const updateFormData = { ...prevFormData, [name]: value.trim() }; handleFormValidation(name, value);
return updateFormData;
});
};

Trim the values to remove unnecessary whitespace. 

Custom Validation Functions

Every type of input comes with its unique validation logic.

const checkValidEmail = (email: string) => /^[\w-.]+@([\w-]+\.)+[\w-
]{2,4}$/.test(email.toLowerCase());
const checkValidPhone = (phone: string) => /^\d{10}$/.test(phone); const checkValidInputText = (text: string) => text.trim() !== '';

Using regex allows you to match complex patterns such as phone numbers and email addresses. 

Handle Field Validation Logic

Validate and set a suitable error message for every field type with a switch-case.

const handleFormValidation = (nameType: string, value: string) => { let errorMsg = '';
switch (nameType) { case 'userName':
if (!checkValidInputText(value)) errorMsg = 'User Name is required.'; break;
case 'email':
if (!checkValidEmail(value)) errorMsg = 'Please enter valid email.'; break;
case 'password':
if (value.length  ({ ...prev, [nameType]: errorMsg }));
};

Display the Form

Dynamic error rendering wraps every input in the field.






Submission Handling

Stop the default submission. Instead, use JavaScript to manage it.

const handleSubmitForm = (event: React.FormEvent) => { event.preventDefault();
// Add final validation or submit logic here
};

Output:

Integration Flow Summary:

  1. Users provide input in the fields. 
  2. The handleOnChange() function will update the state and call handleFormValidation(). 
  3. A corresponding error message is displayed inline below each field in case the input is found to be invalid. 
  4. The form won’t be submitted if errors are found in the input fields.

2.3 Server-side Validation

You cannot depend completely on client-side validations, as malicious actors can manipulate the browser and bypass the security checks. Server-side validation ensures the validity of the given input once the server receives the submitted data. This acts as a double-check to ensure data accuracy even after the failure of client-side assessment or to manage complex validation logic.

The following is the sequence of actions in the combined process of client-side and server-side validation:

  1. Fill out the form and receive immediate feedback if you enter any invalid details in a particular field. You can also get the error details at the end when you click the submit button.
  2. After you submit the form, the details are sent via HTTP requests to the server.
  3. The server again performs the validation on its side according to the specified rules after receiving the details.
  4. If everything is as per the required format, the server processes the received input and responds with success feedback.
  5. If the server encounters any inappropriate data, it responds with an error message containing all the details about the error.

2.4 Dynamic Validation Using Form State

Dynamic validation, i.e., validation not limited to pre-defined rules, can be implemented directly within the React components with the following two techniques:

  1. Updating Validation State Based on User Input: The validation logic is implemented inside the event handlers, and the component’s state gets updated according to the output returned from the event handlers.
  2. Toggling Validation Based on State: The validation state in the component’s render function decides the rendering of validation messages or the modification of form behavior.

3. Various Libraries for Form Validation

We’ll learn three top form validation libraries in React to simplify the form creation and management process and help in creating efficient and user-friendly forms.

3.1 Yup

Yup is a JavaScript library used to build object schemas based on the given data and then validate the data against those schemas. It includes different parsing methods to transform the data according to the defined schema.

Yup is commonly used with Formik and React Hook Form libraries for form validation in React. However, Yup can also be used independently with React to perform form validation. You can first create a schema and then validate the form data against it. Let’s see how we can do it.

  1. Install the Yup package using this command:
    npm install yup
  2. Create a basic form
    import React, { useState } from "react";
    
    // Define TypeScript types for form values
    type FormValues = {
      name: string;
      email: string;
      password: string;
      age: number | string;
    };
    
    const App: React.FC = () => {
      // State to hold form values and errors
      const [formData, setFormData] = useState({
        name: "",
        email: "",
        password: "",
        age: "",
      });
      const [errors, setErrors] = useState>({});
    
      // Handle input changes
      const handleChange = (e: React.ChangeEvent) => {
        const { name, value } = e.target;
        setFormData({
          ...formData,
          [name]: name === "age" ? Number(value) : value,
        });
      };
    
      return (
        
      );
    };
    
    export default App;
    

    Example Output will look like this –

  3. Import the Yup package you installed at the beginning
    import * as yup from 'yup';
  4. Define the schema object against which you want to match the form object. Use the method below for this:
    yup.object().shape()
  5. Assess whether the submitted inputs are correct or not.
    //  Validate and handle form submission
      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        try {
          // Validate the form with Yup
          await validationSchema.validate(formData, { abortEarly: false });
          console.log("Form data:", formData);
          alert("Form submitted successfully!");
          setErrors({});
        } catch (err) {
          if (err instanceof yup.ValidationError) {
            // Map errors to state
            const newErrors: Partial = {};
            err.inner.forEach((error) => {
              if (error.path) {
                newErrors[error.path as keyof FormValues] = error.message;
              }
            });
            setErrors(newErrors);
          }
        }
      };
    
  6. Validation and Getting Error Messages
    // Define Yup schema for validation
      const validationSchema = yup.object().shape({
        name: yup
          .string()
          .min(3, "Name must be at least 3 characters")
          .required("Name is required"),
        email: yup
          .string()
          .email("Invalid email address")
          .required("Email is required"),
        password: yup
          .string()
          .min(6, "Password must be at least 6 characters")
          .max(12, "Password must be no more than 12 characters")
          .required("Password is required"),
        age: yup
          .number()
          .typeError("Age must be a number")
          .min(18, "You must be at least 18 years old")
          .max(99, "Age must be less than 99")
          .required("Age is required"),
      });
    
  7. HandleForm function.
  8. At last, display the error messages on the user interface.

3.2 Formik

Formik is amongst the top open-source and lightweight form management React libraries. It is simple and easy to use. This library uses controlled components to manage the form state within the React component state.

Some of the remarkable characteristics of Formik:

  • Built-in Validation Rules: There are built-in attributes, such as required and minimum/maximum length, in Formik that can help you implement basic validation logic.
  • Custom Validation Logic: You can define your validation function to implement custom validation.
  • Error Handling and Display: Formik manages errors and displays the error message next to the form fields, making it easy for users to understand and resolve those errors.
  • Yup Integration: You can integrate Formik with the schema builder library, Yup, for schema-based form validation.
  • Formik Component: The primary higher-order custom component abstracts the entire form logic.
  • Formik Context: Formik provides a context API to manage and share form state across the component tree in a React application.
  • Declarative: You can focus on business logic as Formik takes care of form states such as field values and touched and visited states, provides built-in error handling mechanisms, synchronizes form values with React state, etc.
  • Intuitive: Formik uses React state and props, controlled components, context, hooks, etc., to build and test forms, making it easy for React developers.
  • Adoptable: Formik does not rely on external state management libraries like Redux or MobX, making it simple and easy to use.

Let’s understand how to build forms using Formik:

  1. Install the Formik library with this command
    npm i formik or yarn add formik
  2. Import the components you want
    import { Formik } from "formik"
  3. The following is an example illustrating the use of Formik hooks
    import React from "react";
    import { Formik } from "formik";
    import * as yup from "yup";
    
    // Define TypeScript types for form values
    type FormValues = {
      name: string;
      email: string;
      password: string;
      age: number | string;
    };
    
    const App: React.FC = () => {
      const initialValues: FormValues = {
        name: "",
        email: "",
        password: "",
        age: "",
      };
    
      // Define Yup schema for validation
      const validationSchema = yup.object().shape({
        name: yup
          .string()
          .min(3, "Name must be at least 3 characters")
          .required("Name is required"),
        email: yup
          .string()
          .email("Invalid email address")
          .required("Email is required"),
        password: yup
          .string()
          .min(6, "Password must be at least 6 characters")
          .max(12, "Password must be no more than 12 characters")
          .required("Password is required"),
        age: yup
          .number()
          .typeError("Age must be a number")
          .min(18, "You must be at least 18 years old")
          .max(99, "Age must be less than 99")
          .required("Age is required"),
      });
    
      return (
         {}}
          validationSchema={validationSchema}
          enableReinitialize
        >
          {({ errors, touched, handleSubmit, setFieldValue }) => {
            return (
              
            );
          }}
        
      );
    };
    
    export default App;
    

3.3 React Hook Form

React Hook Form (RHF) is a minimal React form-building and management library that does so using React hooks. It uses uncontrolled inputs with the ref attribute to take input values from the user without depending on the React component state.

The following are the features of the React Hook Form:

  • Performance: RHF is a highly performant React library owing to its low re-rendering of form components and no dependencies. This is because uncontrolled components preserve the state within the DOM itself, and your time is saved in removing unnecessary re-renders.
  • Functional Approach: React Hook Form uses the useForm hook to instantiate form instances and manage the form state and validation.
  • Built-in Validation Rules: You can use the built-in React form validation attributes, such as pattern and minLength, to implement normal validation scenarios.
  • Custom Validation: You can customize the validation functions according to your form requirements, especially in the case of complex forms. React also integrates with schema validation libraries like Yup and Zod for schema-based validation.
  • Integration with UI Libraries: RHF easily integrates with many of the UI libraries, such as Material UI, Ant-Design, and React-Select, as these libraries also support the ref attribute.
  • Lightweight: The RHF package is very light, having a small file size and zero dependencies, promoting easy installation and usage.
  • Simplicity: It leverages HTML5 standard validation principles and lets you define your validation functions with the help of register functions.

How to Use React Hook Form?

  1. First of all, install this library into your application using
    npm install react-hook-form
    yarn add react-hook-form
    
  2. Include the useForm hook in your file:
    import { useForm } from "react-hook-form";
  3. Create a form using React Hooks’ structured approach
    import React from "react";
    import { FormProvider, useForm } from "react-hook-form";
    import * as yup from "yup";
    import { yupResolver } from "@hookform/resolvers/yup";
    
    // Define TypeScript types for form values
    type FormValues = {
      name: string;
      email: string;
      password: string;
      age: number | string;
    };
    
    const App: React.FC = () => {
      const initialValues: FormValues = {
        name: "",
        email: "",
        password: "",
        age: "",
      };
    
      // Define Yup schema for validation
      const validationSchema = yup.object().shape({
        name: yup
          .string()
          .min(3, "Name must be at least 3 characters")
          .required("Name is required"),
        email: yup
          .string()
          .email("Invalid email address")
          .required("Email is required"),
        password: yup
          .string()
          .min(6, "Password must be at least 6 characters")
          .max(12, "Password must be no more than 12 characters")
          .required("Password is required"),
        age: yup
          .number()
          .typeError("Age must be a number")
          .min(18, "You must be at least 18 years old")
          .max(99, "Age must be less than 99")
          .required("Age is required"),
      });
    
      const methods = useForm({
        defaultValues: initialValues,
        resolver: yupResolver(validationSchema),
        mode: "onChange",
      });
    
      const onSubmit = (data: any) => {
        console.log(data);
      };
    
      return (
        
          
        
      );
    };
    
    export default App;
    

4. Tips and Tricks for Form Validation

We know that forms are an important medium for receiving user information. Therefore, it must follow all the best practices to become robust and user-friendly.

Some tips and tricks to keep in mind while implementing React form validation.

  • Focus on Clarity: Use simple and to-the-point words to write error messages clearly. Try to describe the error message in a few words to help users understand it. For example, use “password must contain only alphanumeric characters” instead of “Invalid Password”. You can even provide suggestions to correct the mistakes to simplify fixing them. Highlight the error-causing field.
  • Universal Accessibility: Your built forms must adhere to the WCAG guidelines to make them accessible to both able and differently abled people, increasing user experience. To ensure this, you must use ARIA attributes like:
    • aria-valuemin: defines the minimum value
    • aria-invalid: specifies the error field
  • Use Form Libraries: Make use of the popular form validation libraries, for example, Formik or React Hook Form, to simplify state management, validation errors, manage form information, etc. The repetitive and time-consuming tasks can be avoided so that you can concentrate on the core functionality.
  • Implement Real-time Feedback: Display the validation results just next to the input fields when users interact with them to ensure instant error identification and rectification. It enhances user experience and is also developer-friendly.
  • Test Your Validation Logic: Check your defined validation functions in different scenarios by developing appropriate unit test cases to remove bugs, if present, before reaching users.
  • Focus on Security: Forms contain sensitive user information hence, data integrity is compulsory. Therefore, implement both client and server-side form validation to prevent any possible security breaches.
  • Cross-Browser Compatibility: The form should give a consistent user experience across all web browsers; hence, remove the browser-specific issues before user interaction.

5. Conclusion

Forms are an essential instrument of data collection and thus provide feedback guiding future developments and updates. We saw above different techniques as well as best practices to apply those validation methods. However, it’s completely your decision regarding the best validation approach based on your form requirements. Implementing an inappropriate technique or library may prove difficult to roll back if found incompatible at any stage. You must understand that server-side validation is unnecessary in forms where client-side validation suffices. Hence, understand the complexities of your project and select the right form validation technique, increasing data accuracy and security.

FAQs

Why use useForm in React?

useForm is a primary custom React hook to help you with form management, error handling, customized validation, and integration easily with UI libraries.

What is the easiest React form?

The Simple React Form framework is the simplest one to make and manage forms in React.

What is Yup in React?

Yup is a JavaScript library used to build object schemas based on the given data and then validate the data according to the built schema.

Comments


Your comment is awaiting moderation.