Capítulo 38 de 39

Chapter 38: FormProvider

Core Idea

FormProvider puts every useForm() method/state on React Context, so any descendant can call useFormContext() and get register/control/handleSubmit/etc. without prop drilling.

Key Concepts

  • FormProvider: takes {...methods} (the full useForm() return) as props and hosts them on context.
  • useFormContext: descendant hook, takes no arguments, returns the same shape useForm() returned at the provider.
  • No nesting: React context doesn't merge — nesting FormProviders means an inner useFormContext() only sees the innermost form, silently breaking registration/validation for consumers expecting the outer form.
  • TTransformedValues generic: FormProviderProps<TFieldValues, TContext, TTransformedValues> (since 7.44.0) types a resolver's transformed output through the provider.

Code Examples

export default function App() {
  const methods = useForm()
  const { register, reset } = methods

  useEffect(() => {
    reset({ name: "data" })
  }, [reset]) // never put `methods` itself as a dependency

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <NestedInput />
        <input {...register("name")} />
      </form>
    </FormProvider>
  )
}

function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods
  return <input {...register("test")} />
}
  • What it demonstrates: a deeply nested NestedInput registers a field without any prop being passed to it — only useFormContext().

Anti-patterns

  • Nesting FormProvider components: consumers inside the inner provider silently bind to the wrong form.
  • Putting methods (the whole object) in a useEffect dependency array: it's a new reference-shape object each render conceptually; depend on the specific method (reset) instead.

Key Takeaways

  1. FormProvider + useFormContext is the standard fix for prop-drilling register/control through deep component trees.
  2. Never nest two FormProviders — context doesn't merge, so the inner one wins entirely for its subtree.
  3. createFormControl's control/methods are a Context-free alternative when you don't want the re-render cost of a Provider subtree.

Connects To

  • useform: the hook whose return value gets spread as FormProvider's props.
  • createformcontrol: an alternative to Context for sharing form state.
  • advanced-usage: the ConnectForm/FormProviderPerformance recipes build directly on this pattern.