React Hook Form
Master React Hook Form — the industry-standard library for forms in React. Learn registration, validation with Zod, error handling, and the patterns used in enterprise applications.
Last reviewed: January 2025
🔍 What Is It?
React Hook Form provides a simple hook-based API for form management:
const { register, handleSubmit, formState: { errors } } = useForm<FormData>();Core API:
- →
register(name, options)— connects an input to RHF (returns ref, onChange, onBlur, name) - →
handleSubmit(fn)— validates the form, then calls your submit function with the data - →
formState.errors— validation errors for each field - →
watch(name)— subscribe to a field's current value - →
setValue(name, value)— programmatically set a field value - →
reset(values)— reset the form (optionally with new default values) - →
Controller— wrapper for controlled third-party inputs (Select, DatePicker, etc.)
🎯 Why Do We Need It?
Manual controlled forms re-render on every keystroke. For a form with 20 fields, typing one character re-renders the entire form. RHF solves this:
- →Performance — uncontrolled inputs, renders only on submit/error
- →Less code — no manual state management for each field
- →Built-in validation — required, min, max, pattern, custom validators
- →Schema validation — Zod/Yup integration for type-safe validation
- →TypeScript first — fully typed form data and errors
- →DevTools — React Hook Form DevTools for debugging
🏗️ What Happens in Real Projects?
RHF is the standard for forms in enterprise React:
- →Multi-step insurance claim submission forms
- →Patient registration forms in healthcare
- →Financial product application forms (mortgage, loan)
- →User profile and settings forms
- →Dynamic forms where fields appear based on other field values
⚙️ How It Works
RHF uses uncontrolled inputs — it attaches a ref to each input and reads values directly from the DOM when needed (on submit or validation trigger). This avoids the re-render-on-every-keystroke problem of controlled inputs.
Validation triggers:
- →
mode: 'onSubmit'(default) — validate only on submit - →
mode: 'onChange'— validate on every change - →
mode: 'onBlur'— validate when field loses focus - →
mode: 'onTouched'— validate on blur, then on change after first blur
Schema validation:
Integrate with Zod via @hookform/resolvers/zod. Define your schema once, get TypeScript types and runtime validation for free.
💻 Example
React Hook Form with Zod Validation — Complete form with schema validation, error handling, and API submission.
🤔 Common Confusions
❓ When should I use register vs Controller?
Use register for native HTML inputs (input, select, textarea) — it attaches a ref directly. Use Controller for third-party components that do not expose a ref (custom Select, DatePicker, Slider, rich text editor). Controller provides a render prop with onChange, onBlur, and value that you pass to the third-party component.
❓ How do I watch a field value to show/hide other fields?
Use the watch function: const claimType = watch("claimType"). This subscribes to the field and returns its current value. Use it in JSX: {claimType === "property" && <AmountField />}. Note: watch causes a re-render on every change — for performance, use getValues() in event handlers when you do not need reactivity.
🚨 Common Production Issues
**Bug: register spread on custom components** — {...register("field")} passes ref, which does not work on custom components. Use Controller for non-native inputs.
**Bug: reset() not working after async data load** — reset() must be called after the data is available. Use useEffect: useEffect(() => { if (data) reset(data); }, [data, reset]).
**Validation mode** — Default mode "onSubmit" means errors only show after the first submit attempt. For better UX, use mode: "onTouched" which validates on blur then on change.
✅ Best Practices
Always use Zod (or Yup) for schema validation — single source of truth for types and validation
Use mode: "onTouched" for better UX than the default "onSubmit" mode
Use setError for server-side validation errors returned from the API
Use reset() with defaultValues to pre-populate forms from API data
Use useFormContext for multi-step forms or deeply nested form components
Install React Hook Form DevTools in development for debugging
🏛️ Architect's Note
React Hook Form with Zod is the standard form solution for enterprise React in 2024. The combination gives you: type-safe form data (Zod infers TypeScript types from the schema), runtime validation, server error handling, and excellent performance. For multi-step forms, use useFormContext to share form state across step components without prop drilling. For very complex dynamic forms (field arrays, conditional schemas), RHF's useFieldArray handles arrays of fields cleanly.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
React Technology Guide
Return to the React learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
Sources
Sources / References
Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide React learning path
Browse the full React topic collection and learning order on SplashRide.
React Interview Prep
Practice React interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
React Controlled Components: Inputs, Checkboxes, and Forms
Build React controlled inputs with value, checked, and onChange. Includes a complete form, reset behavior, number fields, and fixes for uncontrolled-input warnings.
State
Understand React state — the internal memory of a component that drives UI updates. Learn when to use local state, how to structure it, and the patterns senior engineers use to avoid the most common state bugs.