Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/statelyai/xstate/llms.txt

Use this file to discover all available pages before exploring further.

A MachineSnapshot (also called State) represents the state of a state machine actor at a specific point in time. It contains the current state value, context, and other metadata. State snapshots are immutable and represent a point-in-time snapshot of the machine’s state.

Type

type MachineSnapshot<
  TContext extends MachineContext,
  TEvent extends EventObject,
  TChildren extends Record<string, AnyActorRef | undefined>,
  TStateValue extends StateValue,
  TTag extends string,
  TOutput,
  TMeta extends MetaObject,
  TStateSchema extends StateSchema
> = 
  | ActiveMachineSnapshot<...>
  | DoneMachineSnapshot<...>
  | ErrorMachineSnapshot<...>
  | StoppedMachineSnapshot<...>

Properties

value
StateValue
The current state value.This represents the active state nodes in the state machine:
  • For atomic state nodes, it is a string (e.g., "idle")
  • For compound parent state nodes, it is an object (e.g., { red: "walk" })
// Atomic state
snapshot.value; // => "loading"

// Nested states
snapshot.value; // => { red: "walk" }
status
'active' | 'done' | 'error' | 'stopped'
The current status of the snapshot.
  • 'active' - The machine is running normally
  • 'done' - The machine has reached a top-level final state
  • 'error' - The machine encountered an error
  • 'stopped' - The machine has been stopped
context
TContext
The current context (extended state) of the machine.
snapshot.context; // => { count: 42, user: {...} }
output
TOutput | undefined
The output data produced when the machine reaches a top-level final state.Only available when status is 'done'.
if (snapshot.status === 'done') {
  console.log(snapshot.output);
}
error
unknown
The error that caused the machine to enter an error state.Only available when status is 'error'.
if (snapshot.status === 'error') {
  console.error(snapshot.error);
}
tags
Set<string>
The tags of the active state nodes that represent the current state value.
if (snapshot.tags.has('loading')) {
  // Show loading indicator
}
machine
StateMachine
The state machine that produced this state snapshot.
children
Record<string, ActorRef>
An object mapping actor IDs to spawned/invoked actors.
const childActor = snapshot.children.myChild;
historyValue
HistoryValue
The history value of the state, used for history states.

Methods

matches
(stateValue: StateValue) => boolean
Determines whether the current state value is a subset of the given partial state value.
if (snapshot.matches('loading')) {
  // In the 'loading' state
}

if (snapshot.matches({ form: 'valid' })) {
  // In the 'form.valid' state
}
Parameters:
  • stateValue - The state value to match against
Returns: true if the current state matches, false otherwise
hasTag
(tag: string) => boolean
Determines whether the current state has a specific tag.
if (snapshot.hasTag('loading')) {
  // Current state is tagged with 'loading'
}
Parameters:
  • tag - The tag to check for
Returns: true if any active state node has the tag, false otherwise
can
(event: Event) => boolean
Determines whether sending the event will cause a non-forbidden transition to be selected.
if (snapshot.can({ type: 'SUBMIT' })) {
  // The SUBMIT event can be handled
}
Parameters:
  • event - The event to test
Returns: true if the event will cause a transition, false otherwise
getMeta
() => Record<string, any>
Returns the meta data of all active state nodes.
const meta = snapshot.getMeta();
// => { 'loading': { message: 'Loading...' } }
Returns: An object mapping state node IDs to their meta data
toJSON
() => object
Returns a JSON-serializable representation of the snapshot.
const json = snapshot.toJSON();
Returns: A plain object representation of the snapshot

Examples

Checking state values

import { createMachine, createActor } from 'xstate';

const machine = createMachine({
  initial: 'idle',
  states: {
    idle: {
      on: { START: 'running' }
    },
    running: {
      on: { STOP: 'idle' }
    }
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();

if (snapshot.matches('idle')) {
  console.log('Currently idle');
}

console.log(snapshot.value); // 'idle'

Using context

import { createMachine, createActor, assign } from 'xstate';

const counterMachine = createMachine({
  context: { count: 0 },
  initial: 'active',
  states: {
    active: {
      on: {
        INCREMENT: {
          actions: assign({
            count: ({ context }) => context.count + 1
          })
        }
      }
    }
  }
});

const actor = createActor(counterMachine);
actor.start();

actor.send({ type: 'INCREMENT' });

const snapshot = actor.getSnapshot();
console.log(snapshot.context.count); // 1

Using tags

import { createMachine, createActor } from 'xstate';

const machine = createMachine({
  initial: 'loading',
  states: {
    loading: {
      tags: ['busy'],
      on: { SUCCESS: 'success' }
    },
    success: {
      tags: ['complete']
    }
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();

if (snapshot.hasTag('busy')) {
  console.log('Machine is busy');
}

console.log([...snapshot.tags]); // ['busy']

Checking if events can be handled

import { createMachine, createActor } from 'xstate';

const machine = createMachine({
  initial: 'idle',
  states: {
    idle: {
      on: { START: 'running' }
    },
    running: {
      on: { STOP: 'idle' }
    }
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();

if (snapshot.can({ type: 'START' })) {
  console.log('Can send START event');
  actor.send({ type: 'START' });
}

if (!snapshot.can({ type: 'STOP' })) {
  console.log('Cannot send STOP event in current state');
}

Working with nested states

import { createMachine, createActor } from 'xstate';

const machine = createMachine({
  initial: 'auth',
  states: {
    auth: {
      initial: 'loggedOut',
      states: {
        loggedOut: {
          on: { LOGIN: 'loggedIn' }
        },
        loggedIn: {}
      }
    }
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();

console.log(snapshot.value); // { auth: 'loggedOut' }

if (snapshot.matches({ auth: 'loggedOut' })) {
  console.log('User is logged out');
}

Accessing child actors

import { createMachine, createActor, fromPromise } from 'xstate';

const childLogic = fromPromise(async () => {
  return { data: 'result' };
});

const machine = createMachine({
  initial: 'loading',
  states: {
    loading: {
      invoke: {
        id: 'dataFetcher',
        src: childLogic,
        onDone: 'success'
      }
    },
    success: {}
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();
const childActor = snapshot.children.dataFetcher;

if (childActor) {
  console.log('Child actor exists:', childActor.id);
}

Getting meta data

import { createMachine, createActor } from 'xstate';

const machine = createMachine({
  initial: 'loading',
  states: {
    loading: {
      meta: {
        message: 'Loading data...'
      },
      on: { SUCCESS: 'success' }
    },
    success: {
      meta: {
        message: 'Data loaded successfully'
      }
    }
  }
});

const actor = createActor(machine);
actor.start();

const snapshot = actor.getSnapshot();
const meta = snapshot.getMeta();

console.log(meta); // { loading: { message: 'Loading data...' } }

See also

Build docs developers (and LLMs) love