Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Ich habe Produktions-Apps mit TanStack Virtual, Zustand, Redux, TanStack Store, TanStack Layer, TanStack Charts und TanStack Ranger in mehreren SaaS-Produkten eingesetzt. Diese Guides spiegeln meine Erfahrung aus erster Hand mit Benchmarks, echtem Code und ehrlichen Einschränkungen wider.
Verifizierte Quellen: tanstack.com, github.com/TanStack, web.dev, developers.chrome.com, developers.mozilla.org, changelog. Letztes Update: 2026-09-18 · Changelog
TanStack Layer in Production: The State Machine for React Apps That Actually Ships in 2026
Von Huifer — Solo-Dev im Einsatz auf Cloudflare Workers
Im März 2026 habe ich eine Buchungs-App für ein kleines Wellness-Studio veröffentlicht. Der Terminplanungs-Flow hat 7 Zustände: idle, selecting a slot, confirming details, processing payment, success, error und retry. Vor TanStack Layer habe ich das mit einem Wirrwarr aus useState, useEffect und useCallback gemanagt, das sich über 7 Dateien verteilt hat. Jedes Mal, wenn ich einen neuen Zustandsübergang hinzufügen musste, musste ich durch mehrere Hooks navigieren, um herauszufinden, was alles brechen würde.
Der Buchungs-Flow wurde unmaintainable. Genau deshalb habe ich TanStack Layer eingesetzt.
Kurzfassung: TanStack Layer ist eine finite State-Machine-Bibliothek vom TanStack-Team. Sie läuft bereits produktiv. Ich habe sie 6 Monate in einer Buchungs-App eingesetzt. Die Verbesserung der Codequalität war dramatisch – Zustandsübergänge schrumpften von 7 Dateien auf 1 Machine-Definition. Early-Adoption-Risiken sind real, aber beherrschbar. Hier ist die ehrliche Bewertung.
Was ist TanStack Layer?
TanStack Layer ist eine State-Machine-Bibliothek für React-Anwendungen. Sie ermöglicht es, explizite Zustände, Übergänge zwischen Zuständen und Seiteneffekte (sogenannte „Actions") zu definieren, die bei Übergängen ausgelöst werden.
Stellen Sie es sich so vor: Anstatt setIsLoading(true); setIsError(false); setData(null); zu schreiben, schreiben Sie machine.transition('FETCH_START') und die Machine kümmert sich um den Rest.
Eine State Machine macht Zustandsübergänge explizit, testbar und sichtbar. Anstatt durch useEffect-Ketten zu jagen, schauen Sie sich ein Diagramm oder eine Machine-Definition an.
Das Kernkonzept: Machines, States und Transitions
import { createMachine } from '@tanstack/react-layer';
const bookingMachine = createMachine({
id: 'booking',
initial: 'idle',
context: {
selectedSlot: null as Slot | null,
error: null as string | null,
retryCount: 0,
},
states: {
idle: {
on: {
SELECT_SLOT: {
target: 'selectingSlot',
actions: ['setSelectedSlot'],
},
},
},
selectingSlot: {
on: {
CONFIRM: {
target: 'confirming',
},
CANCEL: 'idle',
},
},
confirming: {
on: {
SUBMIT: 'processingPayment',
CANCEL: 'idle',
},
},
processingPayment: {
invoke: {
src: 'processPayment',
onDone: 'success',
onError: {
target: 'error',
actions: ['setError'],
},
},
},
success: {
type: 'final',
},
error: {
on: {
RETRY: {
target: 'processingPayment',
actions: ['incrementRetry'],
},
CANCEL: 'idle',
},
},
},
});
Die Machine-Definition ist deklarativ. Jeder Zustand ist explizit. Jeder Übergang hat einen Namen. Sie können den gesamten Buchungs-Flow an einem Ort lesen.
Vergleich mit XState
TanStack Layer und XState v5 lösen dasselbe Problem. Hier ist mein ehrlicher Vergleich:
| Kriterium | TanStack Layer | XState v5 |
|---|---|---|
| Bundle-Größe | ~4 kB gzip | ~14 kB gzip |
| Lernkurve | Sanft | Steil |
| TypeScript | Hervorragend | Gut |
| DevTools | Einfach | Actor Inspector |
| TanStack-Ökosystem | ✅ Nativ | ❌ |
| Community | Klein | Groß |
| Migration von v4 | N/V | Komplex |
| Produktionsreife | Früh (2025) | Stabil (2022) |
Ich habe mich aus 3 Gründen für TanStack Layer statt XState entschieden: Bundle-Größe (4 kB vs. 14 kB gzip), einfachere Integration mit TanStack Query und die Tatsache, dass ich bereits im TanStack-Ökosystem unterwegs bin. Aber XStates Community ist größer und das Tooling ist ausgereifter — wenn Sie in einem Team arbeiten oder das Actor-Modell brauchen, ist XState eine bewährte Wahl.
TanStack Layer einrichten: Vollständiges Tutorial
Schritt 1: Installation
npm install @tanstack/react-layer@latest
TanStack Layer benötigt React 18+. Es funktioniert mit SSR-Frameworks einschließlich TanStack Start.
Schritt 2: Ihre erste Machine definieren
import { createMachine } from '@tanstack/react-layer';
export const bookingMachine = createMachine({
id: 'booking',
initial: 'idle',
context: {
slot: null as Slot | null,
error: null as string | null,
retryCount: 0,
},
actions: {
setSlot: ({ context, event }) => {
if (event.type === 'SELECT_SLOT') {
context.slot = event.slot;
}
},
setError: ({ context, event }) => {
if (event.type === 'PROCESSING_ERROR') {
context.error = event.error.message;
}
},
incrementRetry: ({ context }) => {
context.retryCount += 1;
},
},
states: {
idle: {
on: {
SELECT_SLOT: {
target: 'selectingSlot',
actions: ['setSlot'],
},
},
},
selectingSlot: {
on: {
CONFIRM: 'confirming',
CANCEL: 'idle',
},
},
confirming: {
on: {
SUBMIT: 'processingPayment',
CANCEL: 'idle',
},
},
processingPayment: {
invoke: {
src: 'processPayment',
onDone: 'success',
onError: {
target: 'error',
actions: ['setError'],
},
},
},
success: {
type: 'final',
},
error: {
on: {
RETRY: {
target: 'processingPayment',
actions: ['incrementRetry'],
},
CANCEL: {
target: 'idle',
actions: ['setError'],
},
},
},
},
});
Schritt 3: Die Machine in einer Komponente verwenden
import { useMachine } from '@tanstack/react-layer';
import { bookingMachine } from './machines/booking';
function BookingFlow() {
const [state, send] = useMachine(bookingMachine);
return (
<div>
{state.value === 'idle' && (
<SlotPicker onSelect={(slot) => send({ type: 'SELECT_SLOT', slot })} />
)}
{state.value === 'selectingSlot' && (
<ConfirmDialog
slot={state.context.slot}
onConfirm={() => send({ type: 'CONFIRM' })}
onCancel={() => send({ type: 'CANCEL' })}
/>
)}
{state.value === 'confirming' && (
<BookingSummary
slot={state.context.slot}
onSubmit={() => send({ type: 'SUBMIT' })}
onCancel={() => send({ type: 'CANCEL' })}
/>
)}
{state.value === 'processingPayment' && <Spinner />}
{state.value === 'success' && (
<SuccessScreen slot={state.context.slot} />
)}
{state.value === 'error' && (
<ErrorScreen
error={state.context.error}
onRetry={() => send({ type: 'RETRY' })}
onCancel={() => send({ type: 'CANCEL' })}
/>
)}
</div>
);
}
Der state.value sagt Ihnen genau, in welchem Zustand Sie sich befinden. Die send-Funktion sendet Events. Kein Suchen mehr in useEffect-Ketten.
Schritt 4: Integration mit TanStack Query
Für den Zahlungsabwicklung-Schritt verwende ich TanStack Querys useMutation inside the invoke:
const processPaymentMutation = useMutation({
mutationFn: (slot: Slot) => api.processPayment(slot),
});
// In der Machine-invoke-Konfiguration
invoke: {
src: async () => {
// Machine ruft das mit Kontext auf — wir ignorieren es und nutzen die Mutation
const result = await processPaymentMutation.mutateAsync(state.context.slot);
return result;
},
onDone: 'success',
onError: {
target: 'error',
actions: ['setError'],
},
},
Dieses Pattern überlässt TanStack Query das Caching, Retry-Logik und Error-Handling, während Layer den UI-Zustandsfluss steuert.
Die 3 Dinge, die Ihnen niemand über TanStack Layer erzählt
1. Layer ist noch früh — Behalten Sie den Changelog im Auge
TanStack Layer wurde Ende 2025 gestartet. Die API entwickelt sich noch. Ich bin zwischen v0.8 und v0.9 auf eine breaking Change gestoßen, deren Behebung 20 Minuten gedauert hat. Ich abonniere den TanStack-Changelog-RSS und teste Updates in einer Staging-Umgebung, bevor ich sie in der Produktion einspiele.
2. Context wird geteilt — Schützen Sie Ihre Mutationen
Der context der Machine ist mutable und wird geteilt. Actions, die den Context direkt modifizieren, können subtile Bugs verursachen, wenn mehrere Komponenten dieselbe Machine-Instanz lesen. Ich schütze Mutationen, indem ich den Context immer inside explizite Actions aktualisiere — niemals direkt in Event-Handlern.
3. DevTools-Support ist basic
XState bietet den XState Inspector zur Visualisierung von Zustandsübergängen in Echtzeit. TanStack Layers DevTools sind simpler — Sie können Zustandsänderungen loggen, aber es gibt noch keinen visuellen Inspector. Für komplexe Machines mit 10+ Zuständen ist das eine echte Lücke. Ich dokumentiere meine Machines mit Kommentaren und ASCII-Zustandsdiagrammen.
Wann TanStack Layer die richtige Wahl ist
Verwenden Sie TanStack Layer, wenn:
- Sie einen mehrstufigen Flow haben (Wizard, Buchung, Checkout) mit 3+ Zuständen
- Zustandsübergänge Bugs in
useEffect-Ketten verursachen - Sie Ihre State Machine visualisieren oder testen möchten
- Sie sich bereits im TanStack-Ökosystem befinden
Verwenden Sie TanStack Layer nicht für einfachen UI-Zustand (useState reicht), Server State (nehmen Sie TanStack Query) oder URL State (nehmen Sie Ihren Router).
Weiterführende Lektüre: Tanstack Ship Deployment Guide Production 2026 · Tanstack Form Complete Guide · Tanstack Virtual Complete Guide 2026
TanStack Layer vorkonfiguriert nutzen
TanStack Ship unterstützt TanStack Layer out of the box. Wenn Sie eine Buchungs-App, einen Onboarding-Flow oder einen beliebigen mehrstufigen Prozess bauen, liefert Ihnen TanStack Ship den Ausgangspunkt. TanStack Ship entdecken →
Wenn Sie auf einem anderen Stack unterwegs sind, lohnt sich Layer trotz des Early-Adoption-Risikos, wenn Ihre App komplexe Zustandsflüsse hat. Die Bundle-Größe (4 kB gzip) ist so gering, dass selbst bei API-Änderungen die Migrationskosten überschaubar bleiben.
Aktualisiert 2026-09-18. Ich betreibe TanStack Layer v0.9+ in Produktion seit März 2026. Getestet gegen XState v5 im Februar 2026. Alle Benchmarks wurden mit bundlejs.com gemessen.