Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Technology handbook

TanStack Form

Type-safe fields, validation, async checks, arrays, submission and framework adapters.

Topics
32
Sections
5

Hooks

useField

Read and update one field, with its own validators and meta, from a component.

  • The hook gives one field its value, its handlers and its own meta.
  • Only the component holding that field re-renders when the value changes.
  • Field validators declared here travel with the field wherever it is used.

form.Field

Bind a field through a render prop when the field's state should not lift a whole form render.

  • The render prop keeps field state out of the surrounding component.
  • A parent that never reads the value is never re-rendered by typing in it.
  • It is the right shape when fields are generated from a configuration list.

form.Subscribe

Re-render a small part of the form when a selected piece of form state changes.

  • Subscribing renders only the part that depends on the selected state.
  • A submit button can track validity without the whole form re-rendering.
  • The selector should return a primitive, or the comparison never matches.

useStore with a form selector

Subscribe to a slice of form state - canSubmit, isDirty, errors - instead of the whole store.

  • Reading a slice keeps unrelated keystrokes from touching the subscriber.
  • Submittability, dirtiness and the error map are the usual slices.
  • Selecting the whole store subscribes to everything and defeats the purpose.

formOptions

Declare shared form configuration once and reuse it across client and server.

  • Shared options are declared once and reused by every form that needs them.
  • The same object can be used on the server, which keeps validation identical.
  • Default values declared here are what the field types are inferred from.

useTransform and mergeForm

Merge server-returned state into the client form after a submission.

  • A server response can be merged back into the live form state.
  • This is how server-side errors reach the fields that caused them.
  • The merge keeps what the user typed instead of resetting the form.

Field-level validators

Attach sync and async validation to the field that owns it, with its own debounce.

  • A field validates itself, so moving it does not move its rules.
  • Each field can have its own timing and its own debounce interval.
  • Errors returned here are already associated with the field that owns them.

Array fields

Add, remove and reorder rows while keeping each row's validation and meta attached.

  • Rows are addressed by index, and the API keeps their state aligned on change.
  • Each row keeps its own validation and touched state across a reorder.
  • Push, insert and remove through the form rather than mutating the array.

Form fundamentals

useForm

Create a form with typed default values that drive every field's inferred type.

  • Default values define the shape, and every field path is checked against it.
  • The form owns the values; fields are views onto paths within them.
  • The submit handler receives the whole validated value in one place.

Field components

Subscribe a single field to its own path so unrelated edits do not rerender it.

  • A field subscribes to one path, so typing in it does not render its siblings.
  • This is what keeps a long form responsive as it grows.
  • The component decides its own markup; the library supplies only state.

Typed field paths

Reach nested values with paths the compiler checks against the form's shape.

  • A path is checked against the value shape, so a typo is a compile error.
  • Nested objects and arrays are reachable with dotted and indexed paths.
  • Renaming a field surfaces at every place that referenced it.

Field state

Read touched, dirty, pending and error state to decide what the field should show.

  • Touched separates a field the user has visited from one they have not.
  • Dirty says the value differs from the default, which drives unsaved-change prompts.
  • Showing an error before a field is touched is what makes a form feel hostile.

Default and initial values

Distinguish the value a form starts with from the value a reset returns to.

  • Default values seed an empty form; initial values populate an edit form.
  • Reset returns to whichever of the two the form was constructed with.
  • Loading data after mount needs an explicit reset, not a changed prop.

Controlled inputs

Wire value and change handlers so the form stays the single source of truth.

  • The input reads its value from field state and reports changes back.
  • Mixing in local component state gives two sources of truth that drift.
  • Uncontrolled inputs still work, but their values bypass validation timing.

Validation

Field validators

Validate one value in isolation and return a message the field can render.

  • A field rule sees one value and returns a message or nothing.
  • Keep the message about what the user must do, not about the internal rule.
  • Pure functions here stay testable without rendering the form.

Form-level validators

Express rules that need more than one field, such as matching passwords.

  • Some rules need two values, so they cannot live on either field.
  • Attach the resulting issue to the field the user should correct.
  • Form rules run after the fields pass, so they see validated values.

Validation timing

Choose change, blur or submit per rule so the form corrects rather than nags.

  • Validating on every keystroke reports an error before the entry is finished.
  • Blur is the usual first pass; submit is the guaranteed one.
  • Once a field has failed, revalidating on change lets it recover immediately.

Schema validation

Drive validation from a Zod or Valibot schema and keep one definition of the shape.

  • One schema can validate the form and type the submitted value.
  • The same schema runs on the server, so the two cannot drift apart.
  • Schema issues map onto fields by path with no manual translation.

Async validators

Check availability against a server with debouncing and a pending state that blocks submit.

  • A server check needs a debounce or it fires on every keystroke.
  • Submission must wait for a pending check, or a stale pass slips through.
  • Show the pending state, so the reader knows why submit is disabled.

Error mapping

Return server-side failures onto the specific fields that produced them.

  • A rejected submission returns errors keyed by field path.
  • Mapping them back puts each message next to the input that caused it.
  • A single banner saying the save failed leaves the reader hunting.

Arrays & dynamic fields

Field arrays

Render a repeating group and keep each row's identity stable across reorders.

  • A stable key per row keeps focus and errors attached through a reorder.
  • Using the array index as the key loses that state the moment rows move.
  • The row component reads its own path rather than the whole array.

Adding and removing rows

Mutate the array through the form API so validation and dirty state stay correct.

  • Mutating through the form keeps validation and dirty state consistent.
  • Removing a row must drop its errors too, or the form stays invalid invisibly.
  • Inserting in the middle shifts every later path, which the API handles.

Nested objects

Model grouped fields as an object and validate the group as a unit.

  • Grouped fields validate as a unit when the group has its own rule.
  • Paths mirror the shape, so an address block reads as one object.
  • The submitted value arrives already nested, needing no reassembly.

Conditional fields

Show and validate a field only while another value makes it relevant.

  • A hidden field should stop validating, or submit fails on something invisible.
  • Decide whether hiding clears the value or preserves it for when it returns.
  • Drive visibility from form state rather than from separate component state.

Reordering

Move rows without losing per-row errors or focus.

  • Moving a row keeps its errors, its touched flag and its focus.
  • Reordering is a form operation, not an array mutation done outside it.
  • Announce the move, or a keyboard user has no idea the list changed.

Array-level validation

Enforce minimum and maximum counts separately from each row's own rules.

  • Minimum and maximum counts belong to the array, not to any row.
  • Uniqueness across rows is an array rule with an issue pointing at a row.
  • Row rules still run, so both levels report independently.

Submission & integration

onSubmit

Receive validated values once and perform the write from a single place.

  • The handler receives one validated value, so the write happens in a single place.
  • Validation runs first, so an invalid form never reaches the handler.
  • Throwing here surfaces as a submission error rather than an unhandled rejection.

canSubmit and isSubmitting

Derive button state from the form instead of tracking a separate flag.

  • Derived state removes the separate flag that always drifts out of sync.
  • A submit button disabled on pending async validation prevents a double write.
  • Both come from a subscription, so the button alone re-renders.

Reset and clear

Return to initial values or to empty, and know which one the user expects.

  • Reset returns to the values the form started with, not to empty.
  • Clearing to empty is a different intent and needs explicit values.
  • Resetting after a successful save also drops the unsaved-change warning.

Server actions

Submit to a server function and surface its result without losing entered values.

  • A form can submit to a server function and receive typed results back.
  • Keep the entered values on failure, so the reader does not retype the form.
  • Validate on the server too: the client schema is a convenience, not a guard.

Progressive enhancement

Keep a form usable before hydration and enrich it once the client takes over.

  • A real form element and a method mean the page works before hydration.
  • Client validation then enriches a form that already submits without it.
  • Anything that only exists in JavaScript must not be required to submit.

Framework adapters

Use the binding for React, Vue, Solid or Angular without changing the core model.

  • The core is framework-agnostic; the adapter supplies reactivity.
  • Validation, arrays and submission behave the same across React, Vue and Solid.
  • Only the binding layer changes when a team moves between frameworks.

Sources

  • TanStack Form official documentation

Ask follow-up questions on any topic in your dashboard.

Start learning