Hy coder! Are you building a React application and need to add form validation? Do not worry; we have got you covered. In this article, I'll walk you through the top 4 React form validation libraries: React Hook Form, Formik, Yup, and Final Form. We will break down each library so you can choose the best one for your project.
So let's get started!
The Top 4 Form Validation Libraries
1. React Hook From
Why should we use the React Hook Form?
Weekly downloads via npm: 3m - 4m
npm install react-hook-formimport React, { useState } from "react";
import { useForm } from "react-hook-form";
import "./FormComponent.css";
function App() {
    const { register, handleSubmit, formState: { errors: error } } = useForm({});
    const [submitted, setSubmitted] = useState(false);
    const onSubmit = (data, e) => {
        console.log(data);
        setSubmitted(true);
        e.target.reset();
        setTimeout(() => {
            setSubmitted(false);
        }, 2000);
    };
    return (
        <>
            <form onSubmit={handleSubmit(onSubmit)}>
                <label>First Name</label>
                <input {...register("FirstNameRequired", { required: true, maxLength: 10 })} placeholder="First Name" />
                {error.FirstNameRequired && <p>First Name is required</p>}
                <label>Last Name</label>
                <input {...register("LastNameRequired", { required: true, maxLength: 10 })} placeholder="Last Name" />
                {error.LastNameRequired && <p>Last Name is required</p>}
                {submitted && <div className="success-message">Form has been submitted</div>}
                <input type="submit" />
            </form>
        </>
    );
}
export default App;body {
    background: black;
    font-family: sans-serif;
}
form {
    border: 5px solid #a7a7a7;
    border-radius: 5px;
    padding: 60px 40px;
    max-width: 400px;
    margin: 50px auto;
}
input {
    box-sizing: border-box;
    width: 100%;
    border-radius: 3px;
    padding: 10px 15px;
}
label {
    line-height: 3;
    display: block;
    margin-bottom: 10px;
    margin-top: 20px;
    color: white;
}
button[type="submit"],
input[type="submit"] {
    background: rgb(158, 87, 25);
    color: white;
    text-transform: uppercase;
    border: none;
    cursor: pointer;
    margin-top: 40px;
    padding: 20px;
    letter-spacing: 10px;
}
button[type="submit"],
input[type="submit"]:hover {
    background: rgb(135, 74, 21);
}
.success-message {
    color: rgb(7, 204, 7);
    margin: 10px;
    font-size: 15px;
}
p {
    color: red;
}2. Formik
Why should we use Formik?
npm i formikimport React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import './FormComponent.css';
const App = () => {
    const handleSubmit = (data, { resetForm }) => {
        alert('Form submitted successfully');
        resetForm();
        console.log(data);
    };
    const initialValues = { name: '', email: '', password: '', };
    const validate = values => {
        const errors = {};
        if (!values.name) {
            errors.name = 'Name is required';
        }
        if (!values.email) {
            errors.email = 'Email is required';
        } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
            errors.email = 'Invalid email address';
        }
        if (!values.password) {
            errors.password = 'Password is required';
        } else if (values.password.length < 8) {
            errors.password = 'Password must be at least 8 characters';
        }
        return errors;
    };
    return (
        <div className="form-container">
            <h2 className='heading'>Form Validation with Formik</h2>
            <Formik
                initialValues={initialValues}
                validate={validate}
                onSubmit={handleSubmit}
            >
                <Form>
                    <div className="form-group">
                        <label htmlFor="name">Name</label>
                        <Field type="text" name="name" />
                        <ErrorMessage name="name" component="div" className="error" />
                    </div>
                    <div className="form-group">
                        <label htmlFor="email">Email</label>
                        <Field type="email" name="email" />
                        <ErrorMessage name="email" component="div" className="error" />
                    </div>
                    <div className="form-group">
                        <label htmlFor="password">Password</label>
                        <Field type="password" name="password" />
                        <ErrorMessage name="password" component="div" className="error" />
                    </div>
                    <button type="submit">Submit</button>
                </Form>
            </Formik>
        </div>
    );
};
export default App;* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: cursive;
    color: white;
}
.form-container {
    background-color: rgba(14, 13, 18, 0.933);
    height: 100vh;
}
.heading {
    text-align: center;
    margin-bottom: 20px;
    padding-top: 20px;
}
form {
    border: 5px solid white;
    padding: 50px 30px;
    max-width: 400px;
    margin: 0 auto;
}
.form-group {
    margin-bottom: 20px;
}
input {
    border-radius: 5px;
    width: 100%;
    padding: 8px;
    margin: 5px 0 10px 0;
    font-size: 16px;
    color: black;
}
.error {
    color: red;
}
button {
    padding: 10px 20px;
    margin: 10px 0;
    border-radius: 5px;
    transition: 0.1s all;
    width: 100%;
    letter-spacing: 5px;
    background-color: rgb(177, 94, 108);
    border: none;
    cursor: pointer;
}
button:hover {
    background-color: rgb(163, 84, 97);
}3. Yup Library
Why should we use Yup?
npm i yupimport React, { useState } from 'react';
import * as yup from 'yup';
import './FormComponent.css'
const schema = yup.object().shape({
    name: yup.string().required('Name is required'),
    email: yup.string().email('Invalid email').required('Email is required'),
    password: yup.string().min(8, 'Password must be at least 8 characters').required('Password is required'),
});
const App = () => {
    const [formData, setFormData] = useState({
        name: '',
        email: '',
        password: ''
    });
    const [errors, setErrors] = useState({});
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData({ ...formData, [name]: value });
    };
    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            await schema.validate(formData, { abortEarly: false });
            console.log('Form data:', formData);
            alert('Form has been submitted');
            setFormData({ name: '', email: '', password: '' });
            setErrors({});
        } catch (err) {
            const newErrors = {};
            err.inner.forEach(error => {
                newErrors[error.path] = error.message;
            });
            setErrors(newErrors);
        }
    };
    return (
        <div className='main-container'>
            <div className='heading'>
                <h2>Form Validation with Yup</h2>
            </div>
            <form className='form-group' onSubmit={handleSubmit}>
                <div>
                    <label>Name:</label>
                    <input type="text" name="name" value={formData.name} onChange={handleChange} />
                    {errors.name && <p>{errors.name}</p>}
                </div>
                <div>
                    <label>Email:</label>
                    <input type="text" name="email" value={formData.email} onChange={handleChange} />
                    {errors.email && <p>{errors.email}</p>}
                </div>
                <div>
                    <label>Password:</label>
                    <input type="password" name="password" value={formData.password} onChange={handleChange} />
                    {errors.password && <p>{errors.password}</p>}
                </div>
                <button type="submit">Submit</button>
            </form>
        </div>
    );
};
export default App;* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: cursive;
    color: white;
}
.main-container {
    background-color: rgba(14, 13, 18, 0.933);
    height: 100vh;
}
.heading {
    text-align: center;
    margin-bottom: 20px;
    padding-top: 20px;
}
form {
    border: 5px solid rgb(156, 155, 155);
    padding: 50px 30px;
    max-width: 400px;
    margin: 0 auto;
}
.form-group {
    margin-bottom: 20px;
}
input {
    border-radius: 5px;
    width: 100%;
    padding: 8px;
    margin: 5px 0 10px 0;
    font-size: 16px;
    color: black;
}
div p {
    color: red;
}
button {
    padding: 10px 20px;
    margin: 10px 0;
    border-radius: 5px;
    transition: 0.1s all;
    width: 100%;
    letter-spacing: 5px;
    background-color: rgb(177, 94, 108);
    border: none;
    cursor: pointer;
}
button:hover {
    background-color: rgb(163, 84, 97);
}4. React Final Form
Why should we use React Final Form?
npm i react-final-formimport React from 'react';
import { Form, Field } from 'react-final-form';
import './FormComponent.css'; // Import your CSS file for styling
const initialValues = {
    name: '',
    email: '',
    password: '',
};
const App = () => {
    const handleSubmit = (values, form) => {
        alert('Form submitted successfully');
        form.restart(); // Reset both values and touched states
    };
    const validate = values => {
        const errors = {};
        if (!values.name) {
            errors.name = 'Name cannot be empty';
        }
        if (!values.email) {
            errors.email = 'Email is required';
        } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
            errors.email = 'Invalid email address';
        }
        if (!values.password) {
            errors.password = 'Password is required';
        } else if (values.password.length < 6) {
            errors.password = 'Password must be at least 6 characters';
        }
        return errors;
    };
    return (
        <div className="form-container">
            <h2 className='heading'>Form Validation with Final Form</h2>
            <Form
                initialValues={initialValues}
                onSubmit={handleSubmit}
                validate={validate}
                render={({ handleSubmit }) => (
                    <form onSubmit={handleSubmit}>
                        <div className="form-group">
                            <label htmlFor="name">Name</label>
                            <Field name="name">
                                {({ input, meta }) => (
                                    <div className='error'>
                                        <input {...input} type="text" className={meta.error && meta.touched ? 'error' : ''} />
                                        {meta.error && meta.touched && meta.error}
                                    </div>
                                )}
                            </Field>
                        </div>
                        <div className="form-group">
                            <label htmlFor="email">Email</label>
                            <Field name="email">
                                {({ input, meta }) => (
                                    <div className='error'>
                                        <input {...input} type="email" className={meta.error && meta.touched ? 'error' : ''} />
                                        {meta.error && meta.touched && meta.error}
                                    </div>
                                )}
                            </Field>
                        </div>
                        <div className="form-group">
                            <label htmlFor="password">Password</label>
                            <Field name="password">
                                {({ input, meta }) => (
                                    <div className='error'>
                                        <input {...input} type="password" className={meta.error && meta.touched ? 'error' : ''} />
                                        {meta.error && meta.touched && meta.error}
                                    </div>
                                )}
                            </Field>
                        </div>
                        <button type="submit">Submit</button>
                    </form>
                )}
            />
        </div>
    );
};
export default App;* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: cursive;
    color: white;
}
.form-container {
    background-color: rgba(14, 13, 18, 0.933);
    height: 100vh;
}
.heading {
    text-align: center;
    margin-bottom: 20px;
    padding-top: 20px;
}
form {
    max-width: 400px;
    margin: 0 auto;
}
.form-group {
    margin-bottom: 20px;
}
input {
    border-radius: 5px;
    width: 100%;
    padding: 8px;
    margin: 5px 0 10px 0;
    font-size: 16px;
    color: black;
}
.error {
    color: red;
}
button {
    padding: 10px 20px;
    margin: 10px 0;
    border-radius: 5px;
    transition: 0.1s all;
    width: 100%;
    letter-spacing: 5px;
    background-color: rgb(177, 94, 108);
    border: none;
    cursor: pointer;
}
button:hover {
    background-color: rgb(163, 84, 97);
}
Which one should I choose?
Lots of People Use It: Many React developers like using the React Hook Form. If you need help, there are plenty of others who know how to use it.
Gets Regular Updates: It's always getting better. The people who make React Hook Form are always fixing bugs and adding new stuff.
Flexible: You can customize it to fit your needs. So, you're not stuck with a one-size-fits-all solution.
Lots of Help Available: The React Hook Form comes with lots of guides and examples. If you get stuck, you can find help easily.

