Capítulo 9 de 39

Chapter 9: Form (beta)

Core Idea

<Form> (7.44.0+, beta) is an optional component that submits a validated form to a URL or a Server Action, closely mirroring native <form> behavior — with built-in loading/success/error state, progressive enhancement, and both React Web and React Native support.

Key Concepts

  • Default transport: sends a POST with the data as FormData; set encType="application/json" (or a Content-Type header) to send JSON instead.
  • action: a URL string, or (7.84.0+) a function invoked with the submission's FormData — the Server Action style.
  • method: post/put/delete when action is a URL; GET isn't supported since data goes in the request body.
  • onSubmit: runs after successful client-side validation, before the request — use it to inspect/transform { data, formData, formDataJson, event }.
  • onSuccess / onError: fire after the server responds; onError calls setError internally with key root.server, so errors?.root?.server is how you detect a failed submission in JSX.
  • validateStatus: customize what HTTP status counts as success.
  • progressive: only meaningful for SSR frameworks — combined with useForm({ progressive: true }), RHF's validation rules are rendered as real HTML attributes (required, etc.) so the form works before hydration.
  • render prop: for headless/React Native use, receives { submit } instead of rendering children directly.
  • Data shaping belongs in handleSubmit/onSubmit, not <Form>'s props: if you need to prepare or omit fields before sending, do it in the callback rather than trying to configure it through <Form>.

Code Examples

<Form
  action="/api"
  control={control}
  onSuccess={() => alert("Success")}
  onError={() => alert("error")}
>
  <input {...register("name")} />
  {isSubmitSuccessful && <p>Form submit successful.</p>}
  {errors?.root?.server && <p>Form submit failed.</p>}
  <button>submit</button>
</Form>
  • What it demonstrates: <Form> handling the request itself — success/error state comes straight from formState, no manual fetch/loading state needed.

Reference Tables

PropTypePurpose
actionstring | (formData) => unknownsubmit target (URL or Server Action)
method"post" | "put" | "delete"HTTP method for URL actions
encTypee.g. "application/json"overrides the request Content-Type
onSubmitfunctionruns after validation, before the request
onSuccess / onErrorfunctionpost-response hooks; onError sets errors.root.server
headersobjectrequest headers
validateStatus(status) => booleancustom success-status check
renderfunctionheadless render prop, receives { submit }

Anti-patterns

  • Trying to strip/transform submission fields via <Form>'s own props: use handleSubmit/onSubmit for that instead.

Key Takeaways

  1. <Form> is still beta — evaluate before depending on it for production-critical submission flows.
  2. errors.root.server is the standard place to check for a failed <Form> submission.
  3. progressive (on useForm) + <Form> together are what enable usable, validated HTML before JS hydrates.

Connects To

  • useform-handlesubmit: the lower-level submission primitive <Form> builds on conceptually.
  • useform: the progressive option this component is designed to pair with.
  • advanced-usage: the useActionState-based recipe is the alternative when you need pending/result state beyond what <Form> exposes.