Using Formik and React Hook Form in React – Best Form Libraries (2025)
Forms are an essential part of any React application — from login screens to multi-step registrations.
However, manually managing state, validation, and submission logic can quickly become messy.
That’s where form libraries like Formik and React Hook Form make development cleaner, faster, and more scalable.
In this lesson, you’ll learn:
- What Formik and React Hook Form are
- How to use each one step-by-step
- Their pros, cons, and differences
What is Formik?
Formik is a form management library for React that helps handle:
Form state (values, touched fields, errors)
Validation (manual or with Yup)
Submission logic
Formik keeps your code organized and reduces repetitive state management.
Installation
npm install formik yupExample: Formik + Yup Validation
import React from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
function FormikExample() {
const formik = useFormik({
initialValues: {
name: "",
email: "",
},
validationSchema: Yup.object({
name: Yup.string()
.min(2, "Name must be at least 2 characters")
.required("Name is required"),
email: Yup.string()
.email("Invalid email address")
.required("Email is required"),
}),
onSubmit: (values) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<div>
<label>Name:</label>
<input
name="name"
value={formik.values.name}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.name && formik.errors.name && (
<p style={{ color: "red" }}>{formik.errors.name}</p>
)}
</div>
<div>
<label>Email:</label>
<input
name="email"
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.email && formik.errors.email && (
<p style={{ color: "red" }}>{formik.errors.email}</p>
)}
</div>
<button type="submit">Submit</button>
</form>
);
}
export default FormikExample;
Why Use Formik?
- Handles form state and validation automatically
- Integrates seamlessly with Yup for schema-based validation
- Reduces repetitive
useStateandonChangelogic - Easy to debug and maintain
What is React Hook Form?
React Hook Form (RHF) is a lightweight form library built around React Hooks.
It offers better performance by registering inputs directly and avoiding unnecessary re-renders.
Installation
npm install react-hook-formExample: Basic Form with Validation
import React from "react";
import { useForm } from "react-hook-form";
function RHFExample() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const onSubmit = (data) => alert(JSON.stringify(data, null, 2));
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Name:</label>
<input
{...register("name", { required: "Name is required", minLength: 2 })}
/>
{errors.name && <p style={{ color: "red" }}>{errors.name.message}</p>}
</div>
<div>
<label>Email:</label>
<input
{...register("email", {
required: "Email is required",
pattern: { value: /\S+@\S+\.\S+/, message: "Invalid email" },
})}
/>
{errors.email && <p style={{ color: "red" }}>{errors.email.message}</p>}
</div>
<button type="submit">Submit</button>
</form>
);
}
export default RHFExample;
Why Use React Hook Form?
- Minimal re-renders → faster performance
- Small library size (tiny bundle footprint)
- Works with uncontrolled components (via refs)
- Simple validation syntax without extra libraries
- Great for large or high-performance apps
Formik vs React Hook Form
| Feature / Aspect | Formik | React Hook Form |
|---|---|---|
| Form Management | Controlled (uses React state) | Uncontrolled (uses refs) |
| Performance | Slightly slower (re-renders on change) | Very fast (minimal re-renders) |
| Validation | Schema-based (via Yup) | Built-in or custom rules |
| Ease of Use | Beginner-friendly | Simple but different API |
| Bundle Size | Larger (~15 KB) | Smaller (~8 KB) |
| Best For | Complex enterprise forms | Lightweight, high-speed forms |
Using Yup with React Hook Form
You can combine RHF with Yup for advanced schema validation using @hookform/resolvers.
Install Resolver
npm install @hookform/resolvers yupExample
import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";
function RHFYupExample() {
const validationSchema = Yup.object().shape({
username: Yup.string().required("Username is required"),
age: Yup.number().positive().integer().required("Age is required"),
});
const {
register,
handleSubmit,
formState: { errors },
} = useForm({ resolver: yupResolver(validationSchema) });
const onSubmit = (data) => alert(JSON.stringify(data, null, 2));
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Username:</label>
<input {...register("username")} />
{errors.username && <p style={{ color: "red" }}>{errors.username.message}</p>}
<label>Age:</label>
<input type="number" {...register("age")} />
{errors.age && <p style={{ color: "red" }}>{errors.age.message}</p>}
<button type="submit">Submit</button>
</form>
);
}
export default RHFYupExample;
Best Practices
Use Formik when:
You need complex nested forms
You rely heavily on Yup schemas
You prefer a controlled component approach
Use React Hook Form when:
You want lightweight, fast, and scalable performance
You work with many inputs or dynamic forms
You prefer uncontrolled components