Basic State Machine
Learn how to define a simple toggle machine using the current XState v5 + XMachines setup().createMachine() + definePlayer() pattern.
Use Case
This example demonstrates a toggle switch — the foundation for understanding state machines in XMachines. It is the simplest possible machine: two states, one event type, no router, no catalog.
Complete Code
import { setup } from "xstate";import { definePlayer } from "@xmachines/play-xstate";
// 1. Declare types for context, events, and input via setup()const toggleSetup = setup({ types: { context: {} as { toggleCount: number }, events: {} as { type: "toggle" }, input: {} as { toggleCount?: number } | undefined, },});
// 2. Create the machine using setup().createMachine()const toggleMachine = toggleSetup.createMachine({ id: "toggle", initial: "off", context: ({ input }) => ({ toggleCount: input?.toggleCount ?? 0, }), states: { off: { on: { toggle: { target: "on", actions: toggleSetup.assign({ toggleCount: ({ context }) => context.toggleCount + 1, }), }, }, }, on: { on: { toggle: { target: "off", actions: toggleSetup.assign({ toggleCount: ({ context }) => context.toggleCount + 1, }), }, }, }, },});
// 3. Create a player factoryconst createPlayer = definePlayer({ machine: toggleMachine });
// 4. Create and start an actorconst actor = createPlayer();actor.start();
// 5. Read initial state via getSnapshot()console.log(actor.getSnapshot().value); // "off"console.log(actor.getSnapshot().context.toggleCount); // 0
// 6. Read state via TC39 Signalconsole.log(actor.state.get().value); // "off"
// 7. Send eventsactor.send({ type: "toggle" });console.log(actor.getSnapshot().value); // "on"console.log(actor.getSnapshot().context.toggleCount); // 1
actor.send({ type: "toggle" });console.log(actor.getSnapshot().value); // "off"console.log(actor.getSnapshot().context.toggleCount); // 2
// 8. Cleanupactor.stop();Code Explanation
-
setup({ types })— Declares TypeScript types forcontext,events, andinputbefore the machine is created. This is the XState v5 typed entry point. Never pass type parameters directly tocreateMachine. -
toggleSetup.createMachine(...)— Creates the state machine. Using the scopedtoggleSetup.createMachine(instead of the barecreateMachinefrom xstate) ensures that guards and actions are type-checked against the declared types. -
toggleSetup.assign(...)— Assigns context mutations using the typed setup’sassignhelper. This provides full inference from the declared context type — no manual type assertions needed. -
definePlayer({ machine })— Wraps the machine in a factory. CallingcreatePlayer()returns aPlayerActor— XMachines’ actor type that extends XState’s actor with TC39 Signal reactivity and Play Architecture hooks. -
actor.start()— Activates the machine. Always callstart()before sending events. -
actor.getSnapshot()— Returns the current XState snapshot synchronously..valueis the state name;.contextis the typed context object. -
actor.state.get()— TC39 Signal access to the current snapshot. Useful when wiring infrastructure that observes signals (renderers, router bridges). Equivalent toactor.getSnapshot()for one-time reads. -
Event types use dot-separated lowercase —
"toggle"not"TOGGLE". This matches the XMachines convention used throughout the codebase (e.g."auth.login","auth.logout","play.route").
Key Concepts
setup({ types }): The XState v5 typed entry point. Declares context, event, and input shapes before machine creation.definePlayer({ machine }): Creates a factory function that returnsPlayerActorinstances.actor.state: ASignal.State<Snapshot>— TC39 Signals-based reactive handle on the machine snapshot.actor.getSnapshot(): Synchronous snapshot access — use for one-time reads and TypeScript-typed context inspection.- Typed
assign: Always callsetup.assign(...)(not the bareassignfrom xstate) for context mutations.
Next Steps
- Traffic Light Example — Multi-state machine with
meta.routeandformatPlayRouteTransitions - Form Validation Example — Typed context mutations with
setup.assignand guards - Routing Patterns — Adding
meta.routeto states and usingplay.routeevents