React Hook Form
Form state built on uncontrolled inputs, so typing does not re-render the whole form.
What it is
React Hook Form is a performant, flexible, and easy-to-use library for managing forms in React. It leverages uncontrolled components and React hooks to reduce re-renders and improve form performance.
React Hook Form uses the `useForm` hook to handle form state and validation. Inputs are registered via the `register` function, and submission is handled with `handleSubmit`. It supports synchronous and asynchronous validation, form resetting, error tracking, and custom input components.
- Licence
- MIT
- Best known for
- Minimal re-renders through uncontrolled inputs and refs
When to use it
The question documentation cannot answer for you — because it cannot recommend something else.
Reach for it when
- Forms with many fields where per-keystroke re-rendering is noticeable
- You want validation via a schema library such as Zod or Yup
Look elsewhere when
- A two-field form where `useState` is genuinely simpler
Installation
npm install react-hook-formGetting started
The smallest useful thing you can do with it, and what each part means.
import { useForm } from 'react-hook-form';
function MyForm() {
const { register, handleSubmit } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('firstName')} placeholder='First Name' />
<input {...register('lastName')} placeholder='Last Name' />
<button type='submit'>Submit</button>
</form>
);
}const { register, handleSubmit, formState: { errors } } = useForm();
<input {...register('email', { required: true })} placeholder='Email' />
{errors.email && <span>Email is required</span>}Advanced usage
Where the library earns its place over a simpler alternative.
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
const schema = yup.object({ email: yup.string().email().required() });
const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver(schema) });const CustomInput = ({ register, name }) => <input {...register(name)} />;
<CustomInput register={register} name='username' />const { fields, append, remove } = useFieldArray({ control, name: 'friends' });
fields.map((field, index) => <input {...register(`friends.${index}.name`)} />);Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Field value not updating
- Ensure the input is registered with the `register` function and the name matches.
- Validation errors not showing
- Check that `formState.errors` is being destructured from `useForm` and used properly in JSX.
- Dynamic fields not working
- Use `useFieldArray` with the `control` object and ensure proper indexing when mapping fields.
Best practices
- Use uncontrolled components for better performance.
- Leverage schema validation libraries like Yup or Zod for complex forms.
- Use `useFieldArray` for dynamic fields.
- Keep error messages user-friendly and accessible.
- Reset forms using `reset()` when needed, especially after submission.
Alternatives
Comparable options, and the reason you would pick one over the other.
Background
Why it exists, and what it was reacting to.
React Hook Form was created by Bill Luo to simplify form management in React applications. It focuses on minimizing boilerplate, reducing unnecessary re-renders, and providing easy integration with validation libraries like Yup and Zod.
