Quick start
Start here to jump straight into XState and Stately Studio.
This quick start guide will help you get started with XState and Stately Studio. You will learn how to create a state machine, create an actor from that state machine, send events to that actor, and observe the state changes.
The fastest way to start with Stately Studio is to go to state.new. There, you’ll find a starter machine with all the statechart basics ready for you to edit. Read more about Stately Studio.
Installing XState v5
XState is a visual state management and orchestration library for JavaScript and TypeScript.
Install the XState v5 using your preferred package manager:
npm install xstatepnpm install xstateyarn add xstateXState v5 requires TypeScript version 5.0 or greater.
For best results, use the latest TypeScript version. Read more about XState and TypeScript
Create a machine
In XState, a machine is an object that contains all the logic for an actor. In this example, we will create a simple toggle machine that can be in one of two states: Active or Inactive. The toggle event will toggle the state between Active and Inactive.
import { createMachine } from 'xstate';
const toggleMachine = createMachine({
id: 'toggle',
initial: 'Inactive',
states: {
Inactive: {
on: { toggle: 'Active' },
},
Active: {
on: { toggle: 'Inactive' },
},
},
});Read our introduction to state machines and statecharts to familiarize yourself with the concepts.
Create an actor and send events
Machine logic can be used to create an actor. An actor is a running process that can receive messages (events), send messages and change its behavior based on the messages it receives.
import { createMachine, createActor } from 'xstate';
const toggleMachine = createMachine({
// Machine code from above
});
// Create an actor that you can send events to.
// Note: the actor is not started yet!
const actor = createActor(toggleMachine);
// Subscribe to snapshots (emitted state changes) from the actor
actor.subscribe((snapshot) => {
console.log('Value:', snapshot.value);
});
// Start the actor
actor.start(); // logs 'Inactive'
// Send events
actor.send({ type: 'toggle' }); // logs 'Active'
actor.send({ type: 'toggle' }); // logs 'Inactive'Use delayed transitions
Delayed transitions are transitions that automatically happen after a specified interval of time.
export const toggleMachine = createMachine({
id: 'toggle',
initial: 'Inactive',
states: {
Inactive: {
on: { toggle: 'Active' },
},
Active: {
on: { toggle: 'Inactive' },
after: { 2000: 'Inactive' },
},
},
});Handle context data
Context is how you store data in a state machine actor.
import { assign, createMachine } from 'xstate';
export const toggleMachine = createMachine({
id: 'toggle',
context: { count: 0 },
initial: 'Inactive',
states: {
Inactive: {
on: { toggle: 'Active' },
},
Active: {
entry: assign({
count: ({ context }) => context.count + 1,
}),
on: { toggle: 'Inactive' },
after: { 2000: 'Inactive' },
},
},
});Add input
Input is how initial data can be provided to a machine actor.
Guards are used to conditionally allow or disallow transitions.
import { assign, createMachine } from 'xstate';
export const toggleMachine = createMachine({
id: 'toggle',
context: ({ input }) => ({
count: 0,
maxCount: input.maxCount,
}),
initial: 'Inactive',
states: {
Inactive: {
on: {
toggle: {
// Only trigger toggle transition if count is less than maxCount
guard: ({ context }) => context.count < context.maxCount,
target: 'Active',
},
},
},
Active: {
entry: assign({
count: ({ context }) => context.count + 1,
}),
on: { toggle: 'Inactive' },
after: { 2000: 'Inactive' },
},
},
});
const actor = createActor(toggleMachine, {
input: { maxCount: 10 },
});
actor.subscribe((snapshot) => {
console.log('State:', snapshot.value);
});
actor.start();
actor.send({ type: 'toggle' });Use your machine with a framework
import { useMachine } from '@xstate/react';
import { toggleMachine } from './toggleMachine';
const App = () => {
const [state, send] = useMachine(toggleMachine);
return (
<div>
<div>Value: {state.value}</div>
<button onClick={() => send({ type: 'toggle' })}>Toggle</button>
</div>
);
};