home / skills / pproenca / dot-skills / react-hook-form

react-hook-form skill

/skills/.curated/react-hook-form

This skill optimizes client-side forms with React Hook Form by applying best practices for useForm, useWatch, useController, and useFieldArray.

npx playbooks add skill pproenca/dot-skills --skill react-hook-form

Review the files below or copy the command above to add this skill to your agents.

Files (47)
SKILL.md
5.7 KB
---
name: react-hook-form
description: React Hook Form performance optimization for client-side form validation using useForm, useWatch, useController, and useFieldArray. This skill should be used when building client-side controlled forms with React Hook Form library. This skill does NOT cover React 19 Server Actions, useActionState, or server-side form handling (use react-19 skill for those).
---

# React Hook Form Best Practices

Comprehensive performance optimization guide for React Hook Form applications. Contains 41 rules across 8 categories, prioritized by impact to guide form development, automated refactoring, and code generation.

## When to Apply

Reference these guidelines when:
- Writing new forms with React Hook Form
- Configuring useForm options (mode, defaultValues, validation)
- Subscribing to form values with watch/useWatch
- Integrating controlled UI components (MUI, shadcn, Ant Design)
- Managing dynamic field arrays with useFieldArray
- Reviewing forms for performance issues

## Rule Categories by Priority

| Priority | Category | Impact | Prefix |
|----------|----------|--------|--------|
| 1 | Form Configuration | CRITICAL | `formcfg-` |
| 2 | Field Subscription | CRITICAL | `sub-` |
| 3 | Controlled Components | HIGH | `ctrl-` |
| 4 | Validation Patterns | HIGH | `valid-` |
| 5 | Field Arrays | MEDIUM-HIGH | `array-` |
| 6 | State Management | MEDIUM | `formstate-` |
| 7 | Integration Patterns | MEDIUM | `integ-` |
| 8 | Advanced Patterns | LOW | `adv-` |

## Quick Reference

### 1. Form Configuration (CRITICAL)

- `formcfg-validation-mode` - Use onSubmit mode for optimal performance
- `formcfg-revalidate-mode` - Set reValidateMode to onBlur for post-submit performance
- `formcfg-default-values` - Always provide defaultValues for form initialization
- `formcfg-async-default-values` - Use async defaultValues for server data
- `formcfg-should-unregister` - Enable shouldUnregister for dynamic form memory efficiency
- `formcfg-useeffect-dependency` - Avoid useForm return object in useEffect dependencies

### 2. Field Subscription (CRITICAL)

- `sub-usewatch-over-watch` - Use useWatch instead of watch for isolated re-renders
- `sub-watch-specific-fields` - Watch specific fields instead of entire form
- `sub-usewatch-with-getvalues` - Combine useWatch with getValues for timing safety
- `sub-deep-subscription` - Subscribe deep in component tree where data is needed
- `sub-avoid-watch-in-render` - Avoid calling watch() in render for one-time reads
- `sub-usewatch-default-value` - Provide defaultValue to useWatch for initial render
- `sub-useformcontext-sparingly` - Use useFormContext sparingly for deep nesting

### 3. Controlled Components (HIGH)

- `ctrl-usecontroller-isolation` - Use useController for re-render isolation
- `ctrl-avoid-double-registration` - Avoid double registration with useController
- `ctrl-controller-field-props` - Wire Controller field props correctly for UI libraries
- `ctrl-single-usecontroller-per-component` - Use single useController per component
- `ctrl-local-state-combination` - Combine local state with useController for UI-only state

### 4. Validation Patterns (HIGH)

- `valid-resolver-caching` - Define schema outside component for resolver caching
- `valid-dynamic-schema-factory` - Use schema factory for dynamic validation
- `valid-error-message-strategy` - Access errors via optional chaining or lodash get
- `valid-inline-vs-resolver` - Prefer resolver over inline validation for complex rules
- `valid-delay-error` - Use delayError to debounce rapid error display
- `valid-native-validation` - Consider native validation for simple forms

### 5. Field Arrays (MEDIUM-HIGH)

- `array-use-field-id-as-key` - Use field.id as key in useFieldArray maps
- `array-complete-default-objects` - Provide complete default objects for field array operations
- `array-separate-crud-operations` - Separate sequential field array operations
- `array-unique-fieldarray-per-name` - Use single useFieldArray instance per field name
- `array-virtualization-formprovider` - Use FormProvider for virtualized field arrays

### 6. State Management (MEDIUM)

- `formstate-destructure-formstate` - Destructure formState properties before render
- `formstate-useformstate-isolation` - Use useFormState for isolated state subscriptions
- `formstate-getfieldstate-for-single-field` - Use getFieldState for single field state access
- `formstate-subscribe-to-specific-fields` - Subscribe to specific field names in useFormState
- `formstate-avoid-isvalid-with-onsubmit` - Avoid isValid with onSubmit mode for button state

### 7. Integration Patterns (MEDIUM)

- `integ-shadcn-form-import` - Verify shadcn Form component import source
- `integ-shadcn-select-wiring` - Wire shadcn Select with onValueChange instead of spread
- `integ-mui-controller-pattern` - Use Controller for Material-UI components
- `integ-value-transform` - Transform values at Controller level for type coercion

### 8. Advanced Patterns (LOW)

- `adv-formprovider-memo` - Wrap FormProvider children with React.memo
- `adv-devtools-performance` - Disable DevTools in production and during performance testing
- `adv-testing-wrapper` - Create test wrapper with QueryClient and AuthProvider

## How to Use

Read individual reference files for detailed explanations and code examples:

- [Section definitions](references/_sections.md) - Category structure and impact levels
- [Rule template](assets/templates/_template.md) - Template for adding new rules
- Reference files: `references/{prefix}-{slug}.md`

## Related Skills

- For schema validation with Zod resolver, see `zod` skill
- For React 19 server actions, see `react-19` skill
- For UI/UX form design, see `frontend-design` skill

## Full Compiled Document

For the complete guide with all rules expanded: `AGENTS.md`

Overview

This skill captures performance-focused best practices for building client-side forms with React Hook Form. It prioritizes rules that reduce unnecessary re-renders, optimize subscriptions, and improve handling of controlled components and dynamic field arrays. Use it to guide form implementation, refactoring, and code generation for React Hook Form vX client-side scenarios.

How this skill works

The skill inspects form configuration, subscription patterns, controlled component wiring, validation strategies, field-array handling, and state subscription choices. It highlights critical and high-impact rules first (form config and field subscription), then covers integration, state management, and advanced optimizations. Recommendations are concrete: change useForm options, prefer useWatch/useController/useFieldArray where appropriate, and structure validation and default values to minimize runtime cost.

When to use it

  • When creating or refactoring client-side controlled forms with React Hook Form
  • When you need to reduce re-renders or optimize performance in complex forms
  • When integrating UI libraries (MUI, shadcn, Ant Design) with controlled inputs
  • When managing dynamic lists of fields with useFieldArray
  • When configuring validation and resolver behavior for large or dynamic schemas

Best practices

  • Set useForm options for performance: onSubmit validation mode, onBlur reValidateMode, and provide defaultValues
  • Prefer useWatch over watch for isolated subscriptions and avoid watch() inside render for one-time reads
  • Use useController to isolate re-renders of controlled UI components and avoid double-registration
  • Define validation schemas/resolvers outside components to enable caching and use schema factories for dynamic rules
  • Use field.id as keys for useFieldArray maps, provide complete default objects, and avoid multiple useFieldArray instances per name
  • Destructure formState and use useFormState/getFieldState to subscribe only to necessary properties

Example use cases

  • A long form with dependent sections where useWatch isolates re-renders to small subtrees
  • Integrating Material-UI Select and TextField with Controller to prevent entire-form re-renders
  • A dynamic invoice line-items array using useFieldArray with field.id keys and complete default objects
  • Switching from inline validation to a cached resolver for complex schema validation to improve runtime speed
  • Refactoring a form to set defaultValues and shouldUnregister for memory efficiency with conditionally rendered fields

FAQ

Does this skill cover server-side forms or React 19 Server Actions?

No. This skill focuses strictly on client-side usage of React Hook Form. Use a React 19/server-specific guide for server actions and server-side handling.

When should I prefer useWatch over useFormState?

Use useWatch when you need value subscriptions for rendering logic in nested components. UseFormState is preferable when you need specific formState flags isolated (isDirty, isValid) without subscribing to all values.