Capítulo 8 de 39

Chapter 8: control

Core Idea

control is the opaque connector object useForm() returns for wiring Controller, useController, useWatch, useFieldArray, useFormState, and FormProvider to the same form instance — optional wherever the consuming component already sits inside a FormProvider.

Key Concepts

  • Opaque by design: its internal properties are for the library's own use — never read or mutate them directly, only pass the object itself where an API asks for control.
  • The common thread across the controlled-input APIs: every hook/component that isn't register (i.e. anything working with a controlled/third-party input, a watched value, or a field array) needs control unless a FormProvider supplies it implicitly.

Code Examples

function App() {
  const { control, handleSubmit } = useForm<{ firstName: string }>()

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <Controller
        render={({ field }) => <input {...field} />}
        name="firstName"
        control={control}
        defaultValue=""
      />
    </form>
  )
}
  • What it demonstrates: control flowing from useForm() straight into Controller.

Anti-patterns

  • Reading/mutating properties on control directly: it's internal-use only; interact with the form exclusively through the documented hooks/components it's passed to.

Key Takeaways

  1. control is the plumbing every controlled-input API (Controller, useController, useWatch, useFieldArray, useFormState) needs, unless a FormProvider is already in place.
  2. Treat it as opaque — pass it through, never inspect it.

Connects To

  • usecontroller / usecontroller-controller / usewatch / usefieldarray / useformstate: every one of these takes control as a prop.
  • formprovider: the alternative to threading control through props manually.