Actor-based state management & orchestration for complex app logic.
npx @tessl/cli install tessl/npm-xstate@5.21.0XState is a comprehensive state management and orchestration library for JavaScript and TypeScript applications that enables developers to model complex application logic using finite state machines, statecharts, and the actor model. Built with zero dependencies, it provides predictable, robust, and visual ways to handle application workflow state through event-driven programming paradigms.
npm install xstateimport { createMachine, createActor, setup } from "xstate";For CommonJS:
const { createMachine, createActor, setup } = require("xstate");Entry point specific imports:
// Actions
import { assign, raise, sendTo, spawnChild } from "xstate/actions";
// Actors
import { fromCallback, fromPromise, fromObservable } from "xstate/actors";
// Guards
import { and, or, not, stateIn } from "xstate/guards";
// Graph utilities
import { createTestModel, getShortestPaths } from "xstate/graph";
// Development tools
import { devToolsAdapter } from "xstate/dev";import { createMachine, createActor, assign } from "xstate";
// Define a state machine
const toggleMachine = createMachine({
id: "toggle",
initial: "inactive",
context: { count: 0 },
states: {
inactive: {
on: {
TOGGLE: {
target: "active",
actions: assign({ count: ({ context }) => context.count + 1 })
}
}
},
active: {
on: {
TOGGLE: {
target: "inactive",
actions: assign({ count: ({ context }) => context.count + 1 })
}
}
}
}
});
// Create and start an actor
const actor = createActor(toggleMachine);
actor.start();
// Subscribe to state changes
actor.subscribe((snapshot) => {
console.log("State:", snapshot.value);
console.log("Context:", snapshot.context);
});
// Send events
actor.send({ type: "TOGGLE" });XState is built around several key architectural patterns:
Core functionality for creating and configuring state machines with states, transitions, guards, and actions.
function createMachine<
TContext,
TEvent extends { type: string },
TActor = any,
TAction = any,
TGuard = any,
TDelay = string,
TTag = string,
TInput = any,
TOutput = any
>(
config: MachineConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag, TInput, TOutput>
): StateMachine<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag, TInput, TOutput>;
function setup<T extends SetupTypes>(
implementations: T
): {
createMachine<TConfig extends MachineConfig<any, any>>(
config: TConfig
): StateMachine</* type parameters */>;
};Actor system for creating, managing, and communicating with stateful actors that run state machines and other logic.
function createActor<TLogic extends AnyActorLogic>(
logic: TLogic,
options?: ActorOptions<TLogic>
): Actor<TLogic>;
class Actor<TLogic extends AnyActorLogic> {
start(): void;
stop(): void;
send(event: EventFromLogic<TLogic>): void;
subscribe(observer: Observer<SnapshotFrom<TLogic>>): Subscription;
getSnapshot(): SnapshotFrom<TLogic>;
}Comprehensive set of built-in actions for context assignment, event handling, actor communication, and lifecycle management.
function assign<TContext, TExpressionEvent extends { type: string }>(
assignment: Assigner<TContext, TExpressionEvent> | PartialAssigner<TContext, TExpressionEvent>
): ActionFunction<TContext, TExpressionEvent>;
function raise<TEvent extends { type: string }>(
eventOrExpr: TEvent | ((args: ActionArgs<any, any>) => TEvent),
options?: { id?: string; delay?: number }
): ActionFunction<any, any>;
function sendTo<TTargetActor extends AnyActorRef, TEvent extends { type: string }>(
actor: TTargetActor | string | ((args: ActionArgs<any, any>) => TTargetActor | string),
eventOrExpr: TEvent | ((args: ActionArgs<any, any>) => TEvent),
options?: { id?: string; delay?: number }
): ActionFunction<any, any>;Guard functions and combinators for conditional logic in state machine transitions and actions.
function and<TContext, TExpressionEvent extends { type: string }>(
guards: Guard<TContext, TExpressionEvent>[]
): GuardPredicate<TContext, TExpressionEvent>;
function or<TContext, TExpressionEvent extends { type: string }>(
guards: Guard<TContext, TExpressionEvent>[]
): GuardPredicate<TContext, TExpressionEvent>;
function not<TContext, TExpressionEvent extends { type: string }>(
guard: Guard<TContext, TExpressionEvent>
): GuardPredicate<TContext, TExpressionEvent>;
function stateIn<TContext, TExpressionEvent extends { type: string }>(
stateValue: StateValue
): GuardPredicate<TContext, TExpressionEvent>;Testing, visualization, and analysis tools for state machines including model-based testing and path generation.
function createTestModel<TLogic extends AnyActorLogic>(
logic: TLogic,
options?: TestModelOptions
): TestModel<TLogic>;
class TestModel<TLogic extends AnyActorLogic> {
getShortestPaths(options?: TraversalOptions): StatePath[];
getSimplePaths(options?: TraversalOptions): StatePath[];
testPath(path: TestPath, params: TestParam): void;
}
function getShortestPaths<TLogic extends AnyActorLogic>(
logic: TLogic,
options?: TraversalOptions
): StatePath[];interface MachineConfig<
TContext,
TEvent extends { type: string },
TActor = any,
TAction = any,
TGuard = any,
TDelay = string,
TTag = string,
TInput = any,
TOutput = any
> {
id?: string;
initial?: string | InitialTransitionConfig<TContext, TEvent>;
context?: TContext | ContextFactory<TContext, TEvent>;
states?: StatesConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag>;
on?: TransitionsConfig<TContext, TEvent, TAction, TGuard, TDelay>;
entry?: Actions<TContext, TEvent, TAction>;
exit?: Actions<TContext, TEvent, TAction>;
after?: DelayedTransitions<TContext, TEvent, TAction, TGuard, TDelay>;
always?: TransitionConfigOrTarget<TContext, TEvent, TAction, TGuard>[];
invoke?: InvokeConfig<TContext, TEvent, TActor>[];
onDone?: TransitionConfigOrTarget<TContext, DoneStateEvent<TOutput>, TAction, TGuard>[];
tags?: TTag[];
description?: string;
type?: "atomic" | "compound" | "parallel" | "final" | "history";
output?: Mapper<TContext, TEvent, TOutput> | TOutput;
meta?: MetaObject;
}
interface StateMachine<
TContext,
TEvent extends { type: string },
TActor = any,
TAction = any,
TGuard = any,
TDelay = string,
TTag = string,
TInput = any,
TOutput = any
> {
id: string;
config: MachineConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag, TInput, TOutput>;
implementations: MachineImplementations<TContext, TEvent, TActor, TAction, TGuard, TDelay>;
getInitialSnapshot(input?: TInput): MachineSnapshot<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag>;
transition(snapshot: MachineSnapshot<any, any>, event: TEvent): MachineSnapshot<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag>;
}
interface MachineSnapshot<
TContext,
TEvent extends { type: string },
TActor = any,
TAction = any,
TGuard = any,
TDelay = string,
TTag = string
> extends Snapshot<any> {
context: TContext;
value: StateValue;
machine: StateMachine<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag>;
matches(stateValue: StateValue): boolean;
hasTag(tag: TTag): boolean;
can(event: TEvent): boolean;
}
interface ActorRef<TSnapshot extends Snapshot<unknown>, TEvent extends { type: string }> {
id: string;
send(event: TEvent): void;
subscribe(observer: Observer<TSnapshot>): Subscription;
getSnapshot(): TSnapshot;
getPersistedSnapshot(): Snapshot<unknown>;
}
type StateValue = string | { [key: string]: StateValue };
interface EventObject {
type: string;
}
interface AnyEventObject extends EventObject {
[key: string]: any;
}
type MachineContext = Record<string, any>;
interface MetaObject {
[key: string]: any;
}type InputFrom<T> = T extends StateMachine<any, any, any, any, any, any, any, infer TInput, any> ? TInput : never;
type OutputFrom<T> = T extends StateMachine<any, any, any, any, any, any, any, any, infer TOutput> ? TOutput : never;
type StateFrom<T> = T extends StateMachine<infer TContext, infer TEvent, infer TActor, infer TAction, infer TGuard, infer TDelay, infer TTag, any, any>
? MachineSnapshot<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag> : never;
type ContextFrom<T> = T extends StateMachine<infer TContext, any, any, any, any, any, any, any, any> ? TContext : never;
type EventFrom<T> = T extends StateMachine<any, infer TEvent, any, any, any, any, any, any, any> ? TEvent : never;
type SnapshotFrom<T> = T extends ActorLogic<infer TSnapshot, any, any, any, any> ? TSnapshot : never;