Skip to content
Development
Skill

/web-forms-react-hook-form

React Hook Form patterns - useForm, Controller, useFieldArray, validation resolver, performance optimization

From plugin
skills
26200 skills

Claude Code

$ npx -y skills add agents-inc/skills --skill web-forms-react-hook-form --agent claude-code

SKILL.md

web-forms-react-hook-form.SKILL.md
name: web-forms-react-hook-form
description: React Hook Form patterns - useForm, Controller, useFieldArray, validation resolver, performance optimization

React Hook Form Patterns

> **Quick Guide:** `register` binds native inputs and keeps them uncontrolled; `Controller` wraps > components that hold their own value; `useFieldArray` drives repeatable rows and is keyed on > `field.id`. Validation arrives either as `register` rules or as a schema through `resolver`. > Re-renders are the thing to watch: `useWatch` and `useFormState` subscribe to named fields, > whereas `watch()` and a wide `formState` destructure subscribe to the whole form.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — a type-safe form with `register`, error display and accessibility attributes
  • [examples/controlled-components.md](examples/controlled-components.md) — `Controller` around a select, a date picker and a checkbox group
  • [examples/validation.md](examples/validation.md) — wiring a schema in through `resolver`
  • [examples/arrays.md](examples/arrays.md) — `useFieldArray` line items with a live total
  • [examples/performance.md](examples/performance.md) — isolated subscriptions, `FormStateSubscribe`, `useWatch` `exact` and `compute`
  • [examples/form-options.md](examples/form-options.md) — the `values` prop for async data, `disabled`, the `<Form />` component
  • [examples/wizard.md](examples/wizard.md) — multi-step form with per-step `trigger()`
  • [reference.md](reference.md) — decision trees, API tables, version-to-feature lookup

---

Which path applies

  • **A native `input`, `select` or `textarea`** — `register` hands the ref to the form, the field

stays uncontrolled, and typing re-renders nothing. Follow [examples/core.md](examples/core.md).

  • **A component that owns its value** — a custom select, date picker or rich text editor exposes no

usable ref, so `Controller` supplies `value` and `onChange` and confines the re-render to that field. Follow [examples/controlled-components.md](examples/controlled-components.md).

  • **Validation stated as a schema rather than as `register` rules** — pass it through `resolver` and

the field-level `rules` drop out. Follow [examples/validation.md](examples/validation.md).

---

<critical_requirements>

Before writing React Hook Form code

**Call `useForm<FormData>()` with a generic and with `defaultValues` for every field.** The generic types each field path and the submit payload; the defaults mount every input controlled from the first render.

**Key `useFieldArray` rows on `field.id`.** It is the identity RHF assigns the row and it survives add, remove and reorder, which an array index does not.

**Reach for `Controller` as soon as a component holds its own value.** `register` needs a ref that reaches a native input, and a component that does not forward one never joins the form.

**Set `mode` to `"onBlur"` or `"onTouched"`.** The default `"onSubmit"` withholds feedback until the first submit, and `"onChange"` validates on every keystroke.

**Pass schema validation through `resolver`, with the schema in its own module.** A schema outside the component is testable on its own and reusable across forms, and the form keeps only the wiring.

</critical_requirements>

---

**Auto-detection:** react-hook-form, useForm, register, handleSubmit, formState, Controller, useFieldArray, useWatch, useFormContext, useFormState, FormProvider, FormStateSubscribe, SubmitHandler, resolver, shouldUnregister, valueAsNumber

**Applies to:**

  • Form state, submission and validation wiring in React
  • Repeatable field groups that add, remove and reorder
  • Components that hold their own value and need bridging into the form
  • Multi-step flows where one form spans several screens
  • Narrowing re-renders in a form with many fields

**Handled elsewhere:**

  • Authoring the validation schema — `resolver` accepts a schema object and this skill only wires it

in; how the schema states its rules is settled by whatever owns it.

  • Where the initial values came from — the form receives them as a prop or through the `values`

option and fetches nothing itself.

  • Markup and styling of the inputs — every example uses plain elements, so the class names are yours.

---

<philosophy>

Form state lives outside React state. Inputs register themselves with the form and report through a ref, so a keystroke updates the form's own store without re-rendering the component that owns the field. Everything that reads form state — an error message, a computed total, a submit button — opts in by subscribing to a named slice, and a component that subscribes to nothing never re-renders.

This is why the wide reads cost so much. `watch()` in a render body and a `formState` destructure that pulls six properties both subscribe to the entire form, undoing the isolation the library was built for.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: useForm with a generic

The generic, `mode` and `defaultValues` together settle type safety, validation timing and controlled-input warnings.

const {
  register,
  handleSubmit,
  formState: { errors, isSubmitting },
} = useForm<ContactFormData>({
  mode: "onBlur",
  defaultValues: { name: "", email: "", message: "" },
});

Full code: [examples/core.md](examples/core.md)

---

Pattern 2: Controller for components that own their value

`Controller` renders the field itself and hands it `value` and `onChange`. The test for which to reach for: a component whose `ref` forwards to a native input works with `register`, and anything else needs `Controller`.

<Controller
  name="service"
  control={control}
  rules={{ required: "Service is required" }}
  render={({ field, fieldState: { error } }) => (
    <>
      <Select {...field} options={serviceOptions} />
      {error && <span role="alert">{error.message}</span>}
    </>
  )}
/>

Full code: [examples/controlled-components.md](examples/controlled-com

Read more
@agents-inc
Ships withskills

The official skills marketplace for Agents Inc. 230+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Stars on GitHub

Momentum

stars in total
26
Star history of agents-inc/skills on GitHub, a chart by star-history.com

Other skills on skills.

ai-infrastructure-litellm

ai-infrastructure-lite…

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…

@agents-inc@agents-incInstall Skill
ai-infrastructure-modal

ai-infrastructure-moda…

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…

@agents-inc@agents-incInstall Skill
ai-infrastructure-ollama

ai-infrastructure-olla…

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…

@agents-inc@agents-incInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about web-forms-react-hook-form.

Which coding agents can use web-forms-react-hook-form?
web-forms-react-hook-form installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.