Using react-hook-form
In this page:
Why Use a Form Library
For forms with many fields, writing a useState and onChange handler for every single one becomes repetitive and can cause unnecessary re-renders on every keystroke. react-hook-form manages all field state internally using uncontrolled inputs, exposing a simple register() function instead.
Note: react-hook-form is especially popular for large forms (10+ fields) where performance and boilerplate both matter.
Warning: It's an npm package, not built into React — it needs to be installed and can't run in this CDN-only preview sandbox.
Example: Why Use a Form Library
// Run in your local React project (npm install required)
import { useForm } from 'react-hook-form';
function App() {
const { register, handleSubmit } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email')} placeholder="Email" />
<button type="submit">Submit</button>
</form>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Registering Inputs with register()
Calling register(fieldName) returns the props (ref, onChange, onBlur, name) an input needs to be tracked by the form, without you writing them by hand. Spreading its return value onto an <input> wires that field into the form automatically.
Note: You can pass validation rules directly into register, like register(email, { required: true }).
Warning: Forgetting the spread syntax ({...register(email)}) means only some of the required props get attached, breaking tracking silently.
Example: Registering Inputs with register()
// Run in your local React project (npm install required)
import { useForm } from 'react-hook-form';
function App() {
const { register, handleSubmit } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register('username', { required: true })} />
<input {...register('age', { min: 18 })} type="number" />
<button type="submit">Submit</button>
</form>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Reading Validation Errors from formState
When you add validation rules to register(), react-hook-form automatically tracks any failures in formState.errors, keyed by field name. Destructuring formState.errors alongside register and handleSubmit gives you everything needed to show inline error messages.
Note: Check errors.fieldName && <message> right under each input to keep the error close to the field it belongs to.
Warning: formState.errors resets are timing-sensitive — always read it from the same useForm() call, never store it in separate local state.
Example: Reading Validation Errors from formState
// Run in your local React project (npm install required)
import { useForm } from 'react-hook-form';
function App() {
const { register, handleSubmit, formState: { errors } } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register('email', { required: 'Email is required' })} />
{errors.email && <p>{errors.email.message}</p>}
<button type="submit">Submit</button>
</form>
);
}
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
- Forgetting to spread {...register(fieldName)} onto the input, which disconnects it from the form's tracking.
- Mixing react-hook-form's uncontrolled approach with manual useState for the same field.
- Not reading errors from formState, so validation messages never show up.
- react-hook-form manages form state using uncontrolled inputs and refs internally, minimizing re-renders.
- The register() function wires an input into the form without needing useState per field.
- handleSubmit wraps your submit function and only calls it if validation passes.
- formState.errors holds validation messages keyed by field name.
Requires npm install react-hook-form — not available via CDN in this sandbox; works with React 16.8+ (uses hooks internally).
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: