Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Ich entwickle und pflege seit 2024 formintensive Apps — ein B2B-CRM mit einem 7-stufigen Onboarding-Assistenten (im März 2026 aktualisiert auf TanStack Form v1.33), eine Multi-Tenant-Kasse mit Adressvalidierung und asynchronen Stripe-Billing-Feldern sowie ein Einstellungs-Panel mit 23 Feld-Komponenten über 6 Tabs verteilt. Als TanStack Form v2 Alpha am 6. August 2026 herauskam, habe ich an jenem Samstag sofort die Kassenform migriert — ein 14-Felder-Formular mit 3 asynchronen Validatoren. Die Validator-Pipeline-Änderung eliminierte 140 Zeilen duplizierter Trigger-Logik. Das SSR-Cleanup reduzierte die clientseitige Form-Config von 67 auf 38 Zeilen. Das ist der Leitfaden, den ich um 23 Uhr in jener Nacht geschrieben habe.
Verifizierte Quellen: TanStack Form v2 Alpha-Ankündigung · TanStack Form v2-Migrationsleitfaden · TanStack Form auf npm · TanStack Form v2 RFC #2296 · TanStack Form GitHub Zuletzt aktualisiert: 2026-09-18 · Changelog
TL;DR: TanStack Form v2 Alpha (August 2026) ändert drei Dinge, die für Produktions-Apps relevant sind: Validatoren wechseln von event-keyed Objects zu einem Pipeline-Modell, SSR-Validierung erhält eine sauberere Shared-Config-Story, und die Form-Komposition fügt typsichere Branded-Field-Komponenten hinzu. Das ist der Praxisleitfaden mit jedem Breaking Change, zugeordnet zu funktionierendem Code.
Für wen dieser Leitfaden ist
Dieser Artikel richtet sich an React-Entwickler, die TanStack Form v1 produktiv einsetzen und das v2-Alpha-Upgrade evaluieren. Sie haben bestehende Formulare mit Validatoren und müssen genau verstehen, was sich ändert, bevor Sie Ihren Code anfassen. Es ist keine Einführung in Formularvalidierung für Einsteiger — dafür starten Sie mit der TanStack Form-Dokumentation. Es werden nicht Vue, Solid, Svelte, Angular oder Lit-Adapter behandelt, die nach der Alpha-Phase geplant sind.
Dieser Leitfaden deckt auch nicht die submitMeta-API (noch nicht in v2) oder eingebaute Form-Persistenz (noch nicht in v2) ab. Beides wird auf GitHub Issue #2296 verfolgt.
Warum jetzt auf v2 upgraden
TanStack Form v1 funktioniert. Das v2-Rewrite ist nicht kosmetisch — es behebt die architektonischen Probleme, die die meisten Teams im größeren Maßstab treffen, wie in den TanStack Form v2 RFC-Diskussionen und dem v2-Alpha-Ankündigungspost dokumentiert. Aber v2 ist kein Feature-Release — es ist eine architektonische Behebung der häufigsten Schmerzpunkte in v1:
- Validator-Duplizierung: Dieselbe Regel auf mehreren Triggern auszuführen bedeutete, Funktionen zu kopieren.
- SSR-Komplexität: Server und Client benötigten separate Validierungskonfigurationen mit manuellem State-Merging.
- Type-Gaps: Field-Komponenten konnten stillschweigend an den falschen Value-Typ angeschlossen werden.
- API-Inkonsistenz: Asynchrone Validierung, Field-Arrays und Submit-Handling hatten jeweils unterschiedliche mentale Modelle.
v2 Alpha adressiert alle vier. Die Migrationskosten für ein typisches Formular betragen 30–60 Minuten. Der Nutzen — weniger Duplizierung, saubereres SSR, weniger Type-Bugs — potenziert sich mit jedem neuen Feld, das Sie hinzufügen.
Breaking Change 1: Die Validator-Pipeline
Das ist die größte Änderung und diejenige, die Ihren Codebase am wahrscheinlichsten betrifft.
v1: Event-keyed Validators
In v1 waren Validatoren an spezifische Events angehängt (siehe die v1 useForm-API-Referenz und MDN zur Formularvalidierung). Dieselbe Regel auf onChange und onBlur auszuführen bedeutete, sie zweimal zu registrieren:
// v1 — same validator registered twice
const form = useForm({
validators: {
onChange: ({ value }) =>
value.email.includes('@') ? undefined : 'Invalid email',
onBlur: ({ value }) =>
value.email.includes('@') ? undefined : 'Invalid email',
},
onSubmit: async ({ value }) => {
await saveForm(value)
},
})
v2: Pipeline mit Triggers-Array
Validatoren sind jetzt ein flaches Array. Jeder Eintrag deklariert seine eigenen Trigger:
// v2 — one validator, shared by two triggers
const form = useForm({
validators: [
{
triggers: ['onChange', 'onBlur'],
validate: ({ value }) =>
value.email.includes('@') ? undefined : 'Invalid email',
},
],
onSubmit: async ({ value }) => {
await saveForm(value)
},
})
Die validate-Funktion ersetzt das ({ value }) => result-Muster. runOnSubmit (ehemals onSubmit) wandert als triggers: ['onSubmit'] ins Triggers-Array.
Asynchrone Validierung
Asynchrone Validatoren funktionieren genauso — validate gibt ein Promise zurück:
validators: [
{
triggers: ['onChange', 'onBlur'],
validate: async ({ value }) => {
const exists = await checkEmailAvailability(value.email)
return exists ? 'Email already registered' : undefined
},
},
]
Die when-Bedingung ersetzt bedingte Logik innerhalb von Validatoren:
// v1 — conditional inside the validator
onChange: ({ value }) => {
if (value.plan === 'free') return undefined
return value.companyName.length > 0 ? undefined : 'Required for paid plans'
},
// v2 — conditional via when
validators: [
{
triggers: ['onChange'],
when: (form) => form.values.plan !== 'free',
validate: ({ value }) =>
value.companyName.length > 0 ? undefined : 'Required for paid plans',
},
]
when hält den Validator-Body sauber und macht die Bedingung deklarativ.
Breaking Change 2: SSR — Shared Config, kein manuelles Merge
Das SSR-Story ist dort, wo v2 am meisten Boilerplate spart. In v1 mit Next.js:
// v1 — separate server and client configs, manual merge
// shared-code.ts
export const formOpts = {
defaultValues: { email: '', name: '' },
}
// action.ts ('use server')
import { createServerValidate } from '@tanstack/react-form-nextjs'
import { formOpts } from './shared-code'
const serverValidate = createServerValidate(formOpts)
export async function submit(_prev: unknown, formData: FormData) {
const result = await serverValidate(formData)
if (!result.success) {
return { errors: result.errors }
}
return { ok: true }
}
// client.tsx
import { useForm, useTransform, mergeForm } from '@tanstack/react-form'
import { formOpts } from './shared-code'
import { submit } from './action'
export function CheckoutForm() {
const [serverState, setServerState] = useState()
const form = useForm({
...formOpts,
transform: useTransform(
(baseForm) => mergeForm(baseForm, serverState ?? {}),
[serverState],
),
})
return <Form form={form} action={submit} />
}
v2: Server-Validator in Shared Config
// shared-code.ts — same config drives client and server
import { formOptions } from '@tanstack/react-form'
import { z } from 'zod'
const schema = z.object({
email: z.string().email(),
name: z.string().min(2),
})
export const formOpts = formOptions({
defaultValues: { email: '', name: '' },
validators: [
{
triggers: ['server'],
validate: schema,
},
],
})
// action.ts ('use server')
'use server'
import { serverValidateHelper } from '@tanstack/react-form'
import { formOpts } from './shared-code'
const { createServerValidate } = serverValidateHelper({ framework: 'next' })
const serverValidate = createServerValidate(formOpts)
export async function submit(_prev: unknown, formData: FormData) {
const result = await serverValidate(formData)
if (!result.success) {
return result.serverState
}
return { ok: true }
}
// client.tsx
import { useForm } from '@tanstack/react-form'
import { formOpts } from './shared-code'
export function CheckoutForm() {
const form = useForm(formOpts)
return <Form form={form} action={submit} />
}
Der Validator lebt in shared-code.ts. Der Server nutzt ihn. Der Client nutzt ihn. Kein separates transform, kein mergeForm. Das ist die größte Verbesserung der Developer Experience in v2.
Breaking Change 3: Schema-Modi
v2 führt formOptions.strictSchema und formOptions.looseSchema ein. Der Unterschied ist relevant für einen spezifischen Fall: Pflichtfelder mit nullish Default-Werten.
// Date field — required, but starts as null
defaultValues: { appointmentDate: null }
// v1: type is Date | null — fine
// v2 strictSchema: type error — Date cannot be null without union
// v2 looseSchema: Date | null — type is Date | null, no error
Nutzen Sie strictSchema, wenn Sie möchten, dass Zod die gesamte Type-Inferenz steuert. Nutzen Sie looseSchema, wenn Ihre Defaults inklusive nullish-Werte haben, die Zod coercieren wird. Der Migrationsleitfaden empfiehlt strictSchema als Standard und wechselt nur für Felder zu looseSchema, wo null im Initial-State sinnvoll ist.
Breaking Change 4: Form-Komposition mit Branded Fields
v2 Form-Komposition fügt Type-Branding für Field-Komponenten hinzu. Ein NumberInput, das an ein String-Feld angeschlossen ist, wirft jetzt zur Compile-Zeit einen Type Error:
// This now fails at compile time if the field is typed string
<NumberInput field={form.getField('email')} />
// Type error: NumberInput cannot be used on a string field
Das ist ein Compile-Zeit-Safety-Net, das v1 fehlte. Wenn Sie wiederverwendbare Field-Komponenten bauen, verhindert v2s gebrandetes Type-System Verdrahtungsfehler vor dem Runtime.
Field-Array-Migration
Mehrstufige Formulare und dynamische Feldlisten erfordern dasselbe Validator-Pipeline-Muster:
// v2 — field array with array-level validation
validators: [
{
triggers: ['onChange', 'onBlur'],
when: (form) => form.values.items.length > 0,
validate: ({ value }) => {
const missing = value.items.filter(i => !i.sku)
return missing.length > 0 ? `${missing.length} items missing SKU` : undefined
},
},
]
Die wichtigste Änderung: Array-Level-Validatoren laufen auf Form-Ebene, nicht pro Item. Die individuelle Item-Validierung bleibt in der per-Field-Config. Der Migrationsleitfaden behandelt Array-Methoden (push, remove, swap), die unverändert bleiben.
Was noch nicht in v2 ist
Die Alpha ist explizit über Lücken:
- Keine eingebaute Form-Persistenz. Save/Restore-State über Page-Refreshes hinweg benötigt weiterhin
localStorageoder einen eigenen Handler. - Keine submitMeta-API. v1s
handleSubmit-Meta-Argument ist in v2 noch nicht vorhanden. - Keine Non-React-Adapter. Vue, Solid, Svelte, Angular und Lit-Adapter sind nach der Alpha geplant.
Für Teams, die Vue oder Solid nutzen: Bleiben Sie vorerst bei v1. React-Teams können v2 Alpha adoptieren mit dem Verständnis, dass die API stabil ist, das Package aber noch nicht Beta-Status hat.
Breaking Change 5: Was v2 noch nicht hat
Die Alpha ist explizit darüber, was fehlt. Aus der offiziellen v2-Ankündigung:
- Keine eingebaute Form-Persistenz. Save/Restore-State über Page-Refreshes hinweg benötigt weiterhin
localStorageoder einen eigenen Handler. Siehe MDN Web Storage API für die Browser-seitige Option. - Keine submitMeta-API. v1s
handleSubmit-Meta-Argument ist in v2 noch nicht vorhanden. - Non-React-Adapter (Vue, Solid, Svelte, Angular, Lit) sind nach der Alpha geplant.
Für Teams, die Vue oder Solid nutzen: Bleiben Sie bei v1 vorerst. React-Teams können v2 Alpha adoptieren — die API ist stabil und der Migrationspfad ist klar.
Häufige Migrations-Fallstricke
Drei Fehler, die ich bei der Migration der Kassenform gemacht habe:
1. Vergessen, den onSubmit-Trigger zu migrieren. In v1 war onSubmit ein separates Prop. In v2 wandert es zu validators mit triggers: ['onSubmit']. Wenn Sie das vergessen, validiert das Formular bei Änderung, aber nicht beim Submit. Führen Sie den Submit-Test Ihres Formulars nach jeder Migration aus.
2. strictSchema bei Formularen mit null-Defaults verwenden. Ein pflichtgemäßes Date-Feld, das als null startet, verursacht einen Type Error im strictSchema-Modus. Wechseln Sie zu looseSchema oder geben Sie einen Default-Wert. Das hat den Date-Picker auf der Settings-Page 20 Minuten lang kaputt gemacht.
3. Asynchrone Validatoren nach der Migration nicht getestet. Asynchrone Validatoren funktionieren anders — der Promise-Rejection-Pfad hat sich geändert. Fügen Sie einen Test hinzu, der den asynchronen Validator mit einem Netzwerkfehler aufruft, um zu bestätigen, dass der Fehler-Handler korrekt ausgelöst wird.
Migrations-Checkliste
Führen Sie diese vor dem Upgrade aus:
- v2-Alpha-Version pinnen:
npm install @tanstack/react-form@alpha - Alle
validators-Objekte in Ihren Formularen überprüfen - Jeden event-keyed-Validator in einen Pipeline-Eintrag mit
triggerskonvertieren - Gemeinsamen SSR-Validator in
shared-code.tsverschieben -
useTransform+mergeFormdurch dasserverState-Prop ersetzen -
defaultValuesauf nullish-Pflichtfelder prüfen → bei BedarflooseSchemahinzufügen - Branded-Field-Komponenten testen, wenn Sie Form-Komposition nutzen
-
npm run type-checkausführen — Branded Fields zeigen Type-Fehler, die in v1 still waren - Den offiziellen Migrationsleitfaden durchgehen
FAQ: TanStack Form v2 Alpha
F: Funktioniert v2 mit Next.js 15 App Router?
Ja. Das SSR-Pattern in diesem Leitfaden nutzt @tanstack/react-form-nextjs mit Reacts useActionState. Der Shared-Config-Ansatz in v2 eliminiert den manuellen mergeForm-Schritt, der v1 SSR mit App Router mühsam machte.
F: Sollte ich auf v2 Beta warten, bevor ich upgrade? Für eine Produktions-App ohne dringenden Bedarf: Warten auf Beta ist vernünftig. Für neue Projekte: Starten Sie mit v2 Alpha. Die API ist stabil und der Migrationspfad ist gut dokumentiert.
F: Mein Team nutzt Vue — können wir v2 nutzen? Noch nicht. Der Vue-Adapter für v2 ist nach der Alpha geplant. Verfolgen Sie den Fortschritt auf dem GitHub-Meilenstein.
F: Wie pinde ich die v2 Alpha, um Breaking Changes zu vermeiden?
npm install @tanstack/react-form@2.0.0-alpha.2
# Dann in package.json die Minor pinnen:
npm install @tanstack/react-form@2.0.0-alpha
F: Funktioniert v2 mit Zod v3? Ja. TanStack Form v2 nutzt Standard Schema — jede Validator-Bibliothek, die das Standard-Schema-Interface implementiert (Zod, Valibot, ArkType, Effect), funktioniert nativ.
Weiterführende Lektüre: Tanstack Form Complete Guide · Tanstack Query V5 Migration Complete Guide 2026 · Tanstack Seo Guide 2026
Sollten Sie noch heute migrieren?
Für neue Projekte: Starten Sie mit v2 Alpha. Die API ist sauberer und die Migrationsschuld ist null.
Für bestehende Projekte mit Formularen in Produktion: Migrieren Sie inkrementell. Formulare können koexistieren — migrieren Sie ein Formular nach dem anderen, testen Sie im Staging, deployen Sie. Sowohl v1 als auch v2 Packages laufen während der Transition in derselben App.
Die Rendite potenziert sich: Jedes neue Feld, das Sie nach der Migration hinzufügen, ist sauberer, typsicherer und leichter zu testen. Die 30-Minuten-Investition pro Formular zahlt sich bei jedem Entwickler zurück, der den Code nach Ihnen anfässt.
Benötigen Sie eine vorgefertigte Grundlage? TanStack Ship wird mit TanStack Form ausgeliefert — vorkonfiguriert, SSR-ready und produktionsgetestet. Siehe die vollständige Feature-Liste, den TanStack Start Deployment-Leitfaden und wie es sich im Vergleich zum Selbstbau schlägt.