XState i maszyny stanów
Statecharts i Actor Model w React — eliminacja impossible states, wizualizacja flow w Stately Editor i formalne modelowanie UI.
6 narzędzi do zarządzania stanem i flow
XState, Robot, Zag.js, useReducer, Zustand i Redux Toolkit — od formalnych maszyn stanów po proste reducery, każde podejście ma swoje miejsce.
| Narzędzie | Podejście | Rozmiar | Wizualizacja | Ekosystem | Kiedy |
|---|---|---|---|---|---|
| XState v5 | Statecharts + Actor Model | 15KB (core) | Stately Editor / Viz | React, Vue, Svelte, Solid | Złożone flows, enterprise, dokumentacja |
| Robot | Flat FSM | 4KB | Brak (zewnętrzny) | Framework agnostic | Proste maszyny, mały bundle |
| Zag.js | UI component machines | Per komponent | Brak | React, Vue, Solid | Headless accessible UI components |
| useReducer | Reducer pattern | 0KB (wbudowany) | Brak | React only | Proste state logic bez bibliotek |
| Zustand | Flux store | 8KB | Redux DevTools | React first | Global state, nie flow |
| Redux Toolkit | Flux + slices | 15KB+ | Redux DevTools | React | Enterprise, RTK Query, duże aplikacje |
Często zadawane pytania
Co to jest XState i maszyna stanów (State Machine)?
XState: biblioteka do zarządzania stanem opartego na maszynach stanów i statecharts (David Khourshid, 2017). Formal state machines i statecharts z matematyczną precyzją. Maszyna stanów (Finite State Machine): skończona liczba stanów. Tylko jeden stan aktywny w danym momencie. Przejścia (transitions) wyzwalane przez eventy. Przykład: traffic light machine. States: red, yellow, green. Events: TIMER (red->green, green->yellow, yellow->red). Dlaczego maszyny stanów: eliminacja 'impossible states'. Klarowna logika (diagram zamiast if-else). Testowalność (deterministyczna). Dokumentacja (wizualizacja). XState v5 API: createMachine({id: 'trafficLight', initial: 'red', states: {red: {on: {TIMER: 'green'}}, green: {on: {TIMER: 'yellow'}}, yellow: {on: {TIMER: 'red'}}}}). Actor model: interpret(machine) -> actor (observer, można subscription). useMachine(machine) w React -> [state, send]. state.value — aktualny stan. state.context — dane maszyny. send({type: 'TIMER'}) — wyślij event. Context: dane maszyny (rozszerzony stan). Actions: side effects (assign, log, send). Guards: warunki przejść. Services: promises, callbacks, other machines.
Statecharts — rozszerzenie maszyn stanów dla złożonych UI?
Statecharts (David Harel, 1987): rozszerzenie FSM o hierarchię, równoległość i historię. Hierarchiczne stany (nested states): stan może zawierać sub-maszyny. Przykład: logged state zawiera {idle, loading, error} sub-states. Parallel states (type: 'parallel'): wiele stanów aktywnych jednocześnie. Przykład: user settings machine — {theme: {light|dark}, notifications: {on|off}} — oba równolegle. History states: powrót do poprzedniego sub-state po opuszczeniu. shallow (jeden poziom) lub deep (zagnieżdżone). Guards (warunki): przejście tylko gdy warunek spełniony. can({type: 'SUBMIT'}) — sprawdź czy event dozwolony. Actions: entry actions (przy wejściu w stan). exit actions (przy opuszczeniu). transition actions. assign() — modyfikacja context. Invoke: wywołanie promise/observable/callback. Async operations jako states: loading, success, failure — naturalny flow. Przykład form machine: idle -> submitting (invoke: submitForm) -> success | failure. XState Visualizer: stately.ai/viz. Wizualizacja maszyny jako diagram. Import kodu -> interaktywny diagram. Stately Editor: GUI do tworzenia maszyn. Kod generowany automatycznie. Kolaboracja zespołu. XState Inspector: devtools. Wizualizacja runtime state transitions.
XState w React — useActor, useMachine i Actor Model?
XState v5 + React (@xstate/react): useMachine(machine) — lokalna maszyna w komponencie. const [state, send] = useMachine(trafficLightMachine). state.value === 'red'. send({type: 'TIMER'}). useActor(actor) — subscribe do zewnętrznego aktora. Actor Model w XState v5: createActor(machine) — stwórz aktora. actor.start() — uruchom. actor.send({type: 'EVENT'}) — wyślij event. actor.subscribe(state => {...}) — obserwuj stan. actor.stop() — zatrzymaj. Hierarchia aktorów: parent machine spawnuje child actors. spawn(childMachine) — tworzenie sub-aktorów. sendTo(childActor, event) — send do child. Persist state: actor.getPersistedSnapshot() — zapisz stan. createActor(machine, {snapshot}) — przywróć stan. Integration z React Context: globalny actor w Context. useActor per komponent. Nie potrzebujesz Zustand/Redux dla flow logic. XState + TanStack Query: XState dla UI state machine. TanStack Query dla server state. Naturalne rozdzielenie. XState dla: wieloetapowe formularze (wizard). Authentication flow. Real-time systemy (websocket state). Animacje i UI orchestration. Loading states z retry. Checkout process.
Kiedy używać XState zamiast useState lub Zustand?
useState gdy: prosty lokalny stan (toggle, input value, counter). Brak złożonych przejść. Stan nie zależy od historii innych stanów. Zustand gdy: globalny client state. Prosta reaktywność. Brak złożonych flow. XState gdy: stan ma wiele kombinacji (impossible states risk). Wyraźne przejścia (event-driven). Dokumentacja/wizualizacja ważna. Testowanie flow krytyczne. Przykłady idealnych use cases: Form wizard (multi-step checkout): states: personalInfo -> shippingInfo -> payment -> review -> confirming -> confirmed | error. Authentication flow: unauthenticated -> authenticating -> authenticated | error. WebSocket connection: disconnected -> connecting -> connected -> reconnecting. Media player: idle -> loading -> playing -> paused -> ended. Impossible states problem: boolean flags: isLoading, isError, isSuccess — mogą być jednocześnie true. Machine: loading | error | success — niemożliwe jednoczesne. 'Loading and error at the same time' impossible. Decision: simple UI state -> useState. Global app state -> Zustand/Jotai. Complex async flows -> XState. Server state -> TanStack Query. Kombinacja: XState dla flow logic + TanStack Query dla server data + Zustand dla global UI state.
Alternatywy dla XState — Robot, Zag.js, Jotai FSM?
XState nie jest jedyną opcją dla state machines. Robot: minimalistyczny FSM library (4KB). Podobny API do XState v4. Bez statecharts (tylko flat FSM). Dobre dla prostszych use cases. Zag.js: state machine primitives dla UI komponentów (Chakra UI team). Headless UI components bazowane na maszynach stanów. AgnosticL React, Vue, Solid. Accessible (ARIA out-of-the-box). Jotai-fsm: atomowy model + FSM. Małe bundle size. Svelte stores + FSM: Svelte ma wbudowany derived stores. Można implementować FSM patterns. useReducer + TypeScript: wbudowane React. Discriminated unions dla stanów. Brak wizualizacji ani guards systemu. Ale prosty. Redux + Redux Toolkit createSlice: slice per 'machine'. actions jako events. Brak formalności FSM ale podobne podejście. XState v5 zmiany: Actor Model first. createActor zamiast interpret. input prop dla initial context. snapshot API. Mniejszy bundle. Lepszy TypeScript. Implementacja natywna (HTML dialog jako FSM): open/closed stany. Transitions przez events. W natywnym HTML jest FSM wszędzie. Kiedy XState jest najlepszy: produkty enterprise z audytowalnym flow. Duże zespoły (dokumentacja diagramami). Skomplikowane async orchestration. Kiedy pominąć XState: małe projekty. Prosta logika. Team nie zna FSM.
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz