Powerful, type-safe forms for React.
@tanstack/react-form is a headless form state management library built by the TanStack team (creators of React Query and React Table). It provides comprehensive form handling without prescribing any UI components, allowing developers to use their preferred design systems while handling complex validation, field dependencies, and state management.
The library solves the common problem of form libraries being either too opinionated about UI or lacking in type safety. It uses a reactive architecture where only fields affected by state changes re-render, making it suitable for forms with dozens of interdependent fields. Unlike form libraries that require manual TypeScript generics, this package automatically infers types from your defaultValues, catching typos and type mismatches at compile time.
With over 969,000 weekly downloads, @tanstack/react-form is used in production applications requiring robust form handling with strict type safety. It supports modern React patterns including Server Components and SSR, making it compatible with Next.js, Remix, and TanStack Start. The library's architecture separates form logic (FormApi, FieldApi) from rendering, enabling consistent behavior across different UI frameworks and testing environments.
The package integrates with popular validation libraries like Zod, Valibot, and ArkType while also supporting native HTML validation attributes. This flexibility allows teams to choose their validation strategy without being locked into a specific ecosystem, while the headless design means you can use it with Tailwind, Material UI, ShadCN, or any custom component library.
import { useForm } from '@tanstack/react-form';
import { zodValidator } from '@tanstack/zod-form-adapter';
import { z } from 'zod';
const userSchema = z.object({
email: z.string().email('Invalid email address'),
age: z.number().min(18, 'Must be 18 or older'),
newsletter: z.boolean()
});
function UserForm() {
const form = useForm({
defaultValues: {
email: '',
age: 0,
newsletter: false
},
onSubmit: async ({ value }) => {
await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(value)
});
},
validatorAdapter: zodValidator()
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<form.Field
name="email"
validators={{
onChange: userSchema.shape.email
}}
>
{(field) => (
<div>
<input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
onBlur={field.handleBlur}
/>
{field.state.meta.errors && (
<span>{field.state.meta.errors[0]}</span>
)}
</div>
)}
</form.Field>
<form.Field
name="age"
validators={{
onChange: userSchema.shape.age
}}
>
{(field) => (
<div>
<input
type="number"
value={field.state.value}
onChange={(e) => field.handleChange(Number(e.target.value))}
/>
{field.state.meta.errors && (
<span>{field.state.meta.errors[0]}</span>
)}
</div>
)}
</form.Field>
<form.Field name="newsletter">
{(field) => (
<label>
<input
type="checkbox"
checked={field.state.value}
onChange={(e) => field.handleChange(e.target.checked)}
/>
Subscribe to newsletter
</label>
)}
</form.Field>
<form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>
{([canSubmit, isSubmitting]) => (
<button type="submit" disabled={!canSubmit || isSubmitting}>
{isSubmitting ? 'Submitting...' : 'Submit'}
</button>
)}
</form.Subscribe>
</form>
);
}Multi-step wizards with cross-field validation: Building registration flows or checkout processes where fields in later steps depend on earlier choices. The reactive architecture ensures only affected fields re-render when dependencies change, while TypeScript catches invalid field references.
Dynamic forms with conditional fields: Creating admin panels or form builders where fields appear/disappear based on user selections. The programmatic field configuration and form.Field component make it straightforward to render fields conditionally without losing type safety.
Complex data entry forms in enterprise applications: Managing forms with 20+ fields, async validation against APIs, and real-time field dependencies. The granular subscription system prevents performance degradation as form complexity grows.
Server-side rendered forms with progressive enhancement: Building forms that work without JavaScript in Next.js or Remix applications, then enhance with client-side validation. The SSR support and separation of form logic from rendering enables this progressive enhancement pattern.
Form arrays and nested object editing: Handling variable-length lists like adding/removing address entries, order line items, or nested configuration objects. The library's array field support maintains type safety even with dynamic collections.
npm install @tanstack/react-formpnpm add @tanstack/react-formbun add @tanstack/react-form