von Corbin Crutchley am 03. März 2025. 
Wir freuen uns, die erste stabile Version von TanStack Form bekannt zu geben, die jetzt produktionsreif ist! 🥳
Zum Start unterstützen wir fünf Frameworks: React, Vue, Angular, Solid und Lit, sowie eine Vielzahl von Funktionen für jedes spezifische Framework.
$ npm i @tanstack/react-form
# or
$ npm i @tanstack/vue-form
# or
$ npm i @tanstack/angular-form
# or
$ npm i @tanstack/solid-form
# or
$ npm i @tanstack/lit-form
$ npm i @tanstack/react-form
# or
$ npm i @tanstack/vue-form
# or
$ npm i @tanstack/angular-form
# or
$ npm i @tanstack/solid-form
# or
$ npm i @tanstack/lit-form
Es ist fast zwei Jahre her, als ich Tanners BlueSky (damals eine Einladungsplattform) Post sah, in dem er ankündigte, dass er an einem neuen Projekt arbeitete: TanStack Form.

Zu dieser Zeit hatte ich gerade eine alternative Formularbibliothek für React namens "HouseForm" veröffentlicht und war sofort von einigen der Ideen fasziniert, die Tanners Bibliothek bot.
Ich hatte das Glück, bald darauf an einem Hackathon teilzunehmen, an dem auch Tanner teilnahm, und wir konnten Zeit damit verbringen, einige APIs von HouseForm in das Projekt zu integrieren.
Seitdem hat Tanner die Zügel von Form weitgehend an mich und eine wunderbare Gruppe zusätzlicher Betreuer übergeben.
Was haben wir in dieser Zeit gebaut?
Einer der Vorteile, so lange in der Entwicklung zu sein, ist, dass TanStack Form mit einer Fülle von Funktionen startet, die Sie vom ersten Tag an nutzen können.
Lassen Sie uns *nur ein paar* davon anhand von Beispielen des React-Adapters durchgehen.
Wie viele der TanStack-Projekte hat Form revolutioniert, was es bedeutet, eine "typsichere" Formularbibliothek zu sein.
const form = useForm({
defaultValues: {
name: "",
age: 0
}
});
// TypeScript will correctly tell you that `firstName` is not a valid field
<form.Field name="firstName"/>
// TypeScript will correctly tell you that `name`'s type is a `string`, not a `number`
<form.Field name="name" children={field => <NumberInput value={field.state.value}/>}/>
const form = useForm({
defaultValues: {
name: "",
age: 0
}
});
// TypeScript will correctly tell you that `firstName` is not a valid field
<form.Field name="firstName"/>
// TypeScript will correctly tell you that `name`'s type is a `string`, not a `number`
<form.Field name="name" children={field => <NumberInput value={field.state.value}/>}/>
Wir unterstützen sogar die Typprüfung von Fehlern, die in <form.Field> zurückgegeben werden.
<form.Field
name="age"
validators={{
onChange: ({ value }) => (value < 12 ? { tooYoung: true } : undefined),
}}
children={(field) => (
<>
<NumberInput value={field.state.value} />
// TypeScript will correctly tell you that `errorMap.onChange` // is an object,
not a string
<p>{field.state.meta.errorMap.onChange}</p>
</>
)}
/>
<form.Field
name="age"
validators={{
onChange: ({ value }) => (value < 12 ? { tooYoung: true } : undefined),
}}
children={(field) => (
<>
<NumberInput value={field.state.value} />
// TypeScript will correctly tell you that `errorMap.onChange` // is an object,
not a string
<p>{field.state.meta.errorMap.onChange}</p>
</>
)}
/>
Ach ja, wir unterstützen auch feldbezogene Validierung sowie Formularvalidierung. Mischen und kombinieren Sie sie!
Das Beste daran? Sie müssen keine TypeScript-Generics übergeben, um dieses Maß an Typsicherheit zu erhalten. Alles wird aus Ihrer Laufzeitnutzung abgeleitet.
Dank der hervorragenden Arbeit der Ersteller von Zod, Valibot und ArkType unterstützen wir Standard Schema direkt; keine zusätzlichen Pakete erforderlich.
const userSchema = z.object({
age: z.number().gte(13, 'You must be 13 to make an account'),
})
function App() {
const form = useForm({
defaultValues: {
age: 0,
},
validators: {
onChange: userSchema,
},
})
return (
<div>
<form.Field
name="age"
children={(field) => {
return <>{/* ... */}</>
}}
/>
</div>
)
}
const userSchema = z.object({
age: z.number().gte(13, 'You must be 13 to make an account'),
})
function App() {
const form = useForm({
defaultValues: {
age: 0,
},
validators: {
onChange: userSchema,
},
})
return (
<div>
<form.Field
name="age"
children={(field) => {
return <>{/* ... */}</>
}}
/>
</div>
)
}
Das ist aber noch nicht alles! Wir unterstützen auch asynchrone Funktionen zur Validierung Ihres Codes; komplett mit integriertem Debouncing und AbortSignal-basierter Abbruchfunktion.
<form.Field
name="age"
asyncDebounceMs={500}
validators={{
onBlurAsync: async ({ value, signal }) => {
const currentAge = await fetchCurrentAgeOnProfile({ signal })
return value < currentAge ? 'You can only increase the age' : undefined
},
}}
/>
<form.Field
name="age"
asyncDebounceMs={500}
validators={{
onBlurAsync: async ({ value, signal }) => {
const currentAge = await fetchCurrentAgeOnProfile({ signal })
return value < currentAge ? 'You can only increase the age' : undefined
},
}}
/>
Wir unterstützen nicht nur mehrere Frameworks, wie wir von Anfang an erwähnt haben; wir unterstützen mehrere Laufzeitumgebungen. Ob Sie React Native, NativeScript oder sogar SSR-Lösungen wie Next.js oder TanStack Start verwenden, wir haben Sie abgedeckt.
Tatsächlich machen wir bei der Verwendung von SSR-Lösungen die serverseitige Formularvalidierung zum Kinderspiel.
// app/routes/index.tsx, but can be extracted to any other path
import { createServerValidate, getFormData } from '@tanstack/react-form/start'
import { yourSchemaHere } from '~/constants/forms'
const serverValidate = createServerValidate({
...formOpts,
onServerValidate: yourSchemaHere,
})
export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler(
async () => {
return getFormData()
}
)
// app/routes/index.tsx, but can be extracted to any other path
import { createServerValidate, getFormData } from '@tanstack/react-form/start'
import { yourSchemaHere } from '~/constants/forms'
const serverValidate = createServerValidate({
...formOpts,
onServerValidate: yourSchemaHere,
})
export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler(
async () => {
return getFormData()
}
)
Dieses Codebeispiel schließt einige relevante Codeausschnitte aus, um es übersichtlich zu halten. Weitere Details zur SSR-Integration finden Sie in unserer Dokumentation.
Und zack, die exakt gleiche Validierungslogik läuft sowohl auf Ihrem Frontend als auch auf Ihrem Backend. Ihre Formulare zeigen sogar Fehler an, wenn JavaScript im Browser des Benutzers deaktiviert ist!
Wir ruhen uns jedoch nicht auf unseren Lorbeeren aus – wir haben Pläne, v1 um neue Funktionen zu erweitern, jetzt da wir stabil sind. Zu diesen Funktionen gehören:
Und vieles mehr.
Es gibt so viele Leute, denen ich danken möchte, dass ich niemals aufhören würde, wenn ich erst einmal angefangen hätte. Stattdessen spreche ich jede Gruppe von Leuten an, denen ich danken möchte.
Danke an unsere Mitwirkenden: Viele Leute mussten zusammenarbeiten, um dies zu ermöglichen. Von Betreuern anderer TanStack-Projekte, die uns Anleitung gaben, bis hin zu direkten PRs – alles hat uns geholfen, die Ziellinie zu erreichen.
Danke an unsere frühen Anwender: Diejenigen, die ein Risiko mit uns eingegangen sind und wertvolles Feedback zu unseren APIs und Funktionen gegeben haben.
Danke an die Content-Ersteller, die unsere Tools vorgestellt haben: Sie haben mehr Augen auf unser Projekt gelenkt – und es durch Bildung und Feedback besser gemacht.
Danke an die breitere Community: Ihre Begeisterung, unsere Werkzeuge zu nutzen, hat das Team immens angetrieben.
Und zu guter Letzt, **danke** Ihnen, dass Sie sich die Zeit genommen haben, unser neuestes Tool zu lesen und zu erkunden. ❤️