Overview
Want to Master XState Through Working Code?
This guide teaches XState v5 through 80 self-contained, heavily annotated code examples. Each example runs as-is and includes enough commentary to explain not just what the code does, but why it is structured that way. If you already know TypeScript and want to understand state machines without wading through pages of theory before touching code, this is your path.
The examples progress from a single two-state toggle machine all the way to actor-based concurrent systems, React integration, snapshot-based testing, and production patterns used in real applications. You read code, you run code, you modify code — that is the entire method.
What Is By-Example Learning?
By-example learning is a code-first approach. Each entry in this series is a self-contained, runnable program that demonstrates exactly one concept. Every example follows a consistent five-part structure:
- Brief explanation — one to three sentences describing what the example demonstrates
- Optional diagram — a Mermaid diagram when concept relationships benefit from visualization
- Heavily annotated code — the working program with
// =>comments documenting values, states, and side effects at each step - Key takeaway — one or two sentences summarizing the lesson
- Why it matters — fifty to one hundred words connecting the pattern to real-world usage
This structure means you can skim the annotation layer for fast review or read every comment for deep understanding. Both modes work.
What Is XState v5?
XState is a TypeScript-first library for building stateful logic using state machines and the Actor Model. A state machine makes every valid state your application can be in explicit, and defines exactly which events cause transitions between states. The Actor Model extends this to concurrent systems where independent actors communicate by passing messages.
Several distinctions matter before you write a single line:
- XState is not a UI library. It has no opinion on how you render. The
@xstate/reactpackage provides hooks, but the machine itself is framework-agnostic. - XState is not just a store. Stores hold data and let you update it. XState holds data and enforces which updates are legal given the current state — that constraint is the core value.
- XState v5 removed the
interpretfunction in favour ofcreateActor. You create an actor from a machine, start it, and send events to it. - XState v5 replaced
Machine()withcreateMachine(). The new function has a cleaner TypeScript-first API. - XState v5 replaced inline
invokestrings with typed creator functions:fromPromise,fromCallback, andfromObservable. Each clearly expresses the async shape of the invocation. - XState v5 introduced
setup()for defining types, actors, actions, and guards once, then referencing them by string key insidecreateMachine. This is the recommended pattern for full TypeScript inference.
Learning Path
graph TD
A["Beginner Core State Machines Examples 1-27"] --> B["Intermediate Actors, React, Testing Examples 28-54"]
B --> C["Advanced Complex Patterns Examples 55-80"]
D["0% No XState Knowledge"] -.-> A
C -.-> E["95% XState Mastery"]
style A fill:#0173B2,stroke:#000,color:#fff
style B fill:#DE8F05,stroke:#000,color:#fff
style C fill:#029E73,stroke:#000,color:#fff
style D fill:#CC78BC,stroke:#000,color:#fff
style E fill:#029E73,stroke:#000,color:#fff
Accessible color palette: Blue #0173B2, Orange #DE8F05, Teal #029E73, Purple #CC78BC. All colors meet WCAG AA contrast standards and are color-blind friendly.
Coverage Philosophy: 95% Through 80 Examples
The eighty examples are grouped into three tiers that each build on the previous:
Beginner (Examples 1–27) covers the vocabulary every XState program relies on: creating machines, defining states and transitions, guards, actions, context, events, delayed transitions, hierarchical states, parallel states, final states, and history states. By example 27 you can build complete standalone state machines for any synchronous workflow.
Intermediate (Examples 28–54) covers the async and reactive layer: invoking promises with fromPromise, invoking callbacks with fromCallback, invoking observables with fromObservable, spawning child machines as actors, sending messages between actors with sendTo, reading the actor system, React integration with useMachine and useSelector, and snapshot-based testing.
Advanced (Examples 55–80) covers patterns that appear in production codebases: actor registration and lookup, deep actor hierarchies, event forwarding, model-based testing, persisting and restoring state, input actors, custom actor logic, performance patterns, and orchestrating multi-machine systems.
What's Covered
Core Machine Concepts
How createMachine and setup define the complete shape of a machine, including its context type, event union, and actor types.
States and Transitions
Atomic states, compound (hierarchical) states, parallel states, final states, and history states. How events trigger transitions and how default transitions work.
Guards and Actions
Inline guards vs named guards defined in setup. Entry actions, exit actions, transition actions, and assign for updating context. Pure actions vs side-effect actions.
Context and Events
Typed context with initial values, strongly typed event unions, and how assign merges partial context updates. Dynamic context from machine input.
Invocations
fromPromise— invoke an async function, handle resolution and rejectionfromCallback— invoke a callback-based subscription, handle teardownfromObservable— invoke an observable stream, handle completion- Child machines — invoke another machine as a service, communicate via events
Actor Model
Spawning actors with spawn, referencing actors by ActorRef, sending targeted messages with sendTo, reading the actor system registry, and building actor hierarchies.
React Integration
useMachine for local component state, useSelector for subscribing to specific slices of actor state, lifting actor logic out of components for testability, and sharing actors across component trees.
Testing
Creating actors with createActor in tests, sending events programmatically, asserting on getSnapshot(), testing guard and action side effects, and snapshot-based regression testing.
Production Patterns
Actor registration by ID, persisting snapshots to storage and rehydrating machines, passing input to machines via createActor({ input }), composing machines for feature-level encapsulation, and error boundary patterns.
What's NOT Covered
- XState Visualizer internals — the Stately editor and its serialization format are outside the scope of this series
- Non-TypeScript usage — all examples use TypeScript; plain JavaScript adaptation is left to the reader
- XState server package —
@xstate/storeand server-side actor execution are not covered - XState Inspector setup — browser DevTools integration is a separate tooling concern
Setup
mkdir xstate-tutorial && cd xstate-tutorial
npm init -y
npm install xstate
npm install -D typescript tsx @types/node
npx tsc --init --strict true --target ES2022 --module NodeNext --moduleResolution NodeNext
# For React examples (intermediate+):
npm install react react-dom @xstate/react
npm install -D @types/react @types/react-domAll beginner examples run with tsx:
npx tsx example-01.tsReact examples require a bundler such as Vite. The intermediate section includes a minimal Vite + React setup example before the first React integration example.
How to Use This Guide
Run each example with tsx <filename>. Read the // => annotations alongside the code — they show variable values, actor snapshots, and output at each step so you do not need to mentally trace execution.
Each example is self-contained. You do not need to read them in order, though the progression is intentional. The beginner tier assumes no prior XState knowledge. The intermediate tier assumes the beginner tier. The advanced tier assumes both.
Modify every example you read. Change an event name. Add a guard. Remove a state. Breaking things and fixing them is faster than reading the same example twice.
Prerequisites
- TypeScript generics at the level of
<T>type parameters and conditional types async/awaitandPromisechains for the invocation examples- React hooks (
useState,useEffect,useRef) for the React integration examples in the intermediate tier
If you are comfortable with those three areas, you have everything needed to work through all eighty examples.
Ready to Start?
- Beginner — Examples 1–27 — Core state machines, states, transitions, guards, actions, context
- Intermediate — Examples 28–54 — Actors, React, async invocations, testing
- Advanced — Examples 55–80 — Production patterns, persistence, orchestration
Examples by Level
Beginner (Examples 1–27)
- Example 1: createMachine — Blueprint for a State Machine
- Example 2: createActor — Bringing a Machine to Life
- Example 3: States — Exhaustive Named Nodes
- Example 4: Transitions — Per-State Event Routing
- Example 5: Snapshots — Reading the Full Machine State
- Example 6: Guards — Gating Transitions with Predicates
- Example 7: Context — Extended State in the Machine
- Example 8: assign — The Only Way to Update Context
- Example 9: Typed Events with setup()
- Example 10: Guarded Transition Priority Lists
- Example 11: Entry and Exit Actions
- Example 12: Transition Actions
- Example 13: raise — Internal Event Chaining
- Example 14: log — Built-in Logging Action
- Example 15: Multiple Actions — Strict Left-to-Right Order
- Example 16: invoke with fromPromise — Async Operations
- Example 17: invoke with fromCallback — Push-Based Sources
- Example 18: invoke — Parameterizing with input
- Example 19: onDone and onError — Handling Invocation Results
- Example 20: invoke — Child Machines and Machine Output
- Example 21: Compound States — Nested State Hierarchy
- Example 22: Parallel States — Independent Concurrent Regions
- Example 23: History States — Restoring the Last Active Sub-State
- Example 24: Final States — Machine Completion and Output
- Example 25: after — Managed Delayed Transitions
- Example 26: always — Automatic Eventless Routing
- Example 27: Self-Transitions — Internal vs External
Intermediate (Examples 28–54)
- Example 28: Actors vs Machines — The Actor Model
- Example 29: fromPromise — Promise Actors
- Example 30: fromCallback — Callback Actors
- Example 31: fromObservable — Observable Actors
- Example 32: fromTransition — Reducer Actors
- Example 33: spawn — Creating Child Actors
- Example 34: sendTo — Messaging Between Actors
- Example 35: Actor System — system.get()
- Example 36: Machine Input — Parameterizing Machines
- Example 37: Machine Output — Final State Results
- Example 38: setup() — Full TypeScript Type Safety
- Example 39: Tags — Categorizing States
- Example 40: useMachine — React Hook Basics
- Example 41: useSelector — Optimized Re-renders
- Example 42: useActorRef — Accessing Actor Reference
- Example 43: Providing Actors via Context
- Example 44: useMachine with Input
- Example 45: Subscribing to Actor Outside React
- Example 46: Testing Machines with createActor
- Example 47: Asserting State with snapshot.matches
- Example 48: Testing Invocations — Mocking Services
- Example 49: simulate — Step-by-Step Machine Simulation
- Example 50: snapshot.status — Testing Final States
- Example 51: getPersistedSnapshot — Saving State
- Example 52: fromSnapshot — Restoring State
- Example 53: pure and choose — Conditional Actions
- Example 54: enqueueActions — Imperative Action Batching
Advanced (Examples 55–80)
- Example 55: Actor Tree — Spawning a Two-Child Hierarchy
- Example 56: Mediator Pattern — Parent Routes Child Events
- Example 57: Actor Pools — Round-Robin Worker Dispatch
- Example 58: system.get() — Retrieving Actors by System ID
- Example 59: Authentication Flow
- Example 60: Multi-Step Wizard
- Example 61: WebSocket Connection Machine
- Example 62: Data Fetching with Exponential Backoff Retry
- Example 63: Optimistic Update
- Example 64: XState + React Query
- Example 65: XState + Effect.ts
- Example 66: XState + Zustand
- Example 67: XState + React Hook Form
- Example 68: Model-Based Testing with @xstate/graph
- Example 69: Testing Actor Systems with Subscriptions
- Example 70: Simulated Clock for Delayed Transitions
- Example 71: Pure Transitions with machine.transition()
- Example 72: Deep History States
- Example 73: Snapshot Serialization and Restoration
- Example 74: XState Inspector and DevTools
- Example 75: XState v4 → v5 Migration Reference
- Example 76: Statechart vs Reducer — When XState Adds Value
- Example 77: Preventing Impossible States with setup() Types
- Example 78: Server-Side Rendering and Client Hydration
- Example 79: Deferred Events with raise and Cancellation
- Example 80: Production Actor System — Full Mini-Service
Last updated April 28, 2026