Actor-based state management & orchestration for complex app logic. → Documentation
XState is a state management and orchestration solution for JavaScript and TypeScript apps. It has zero dependencies, and is useful for frontend and backend application logic.
It uses event-driven programming, state machines, statecharts, and the actor model to handle complex logic in predictable, robust, and visual ways. XState provides a powerful and flexible way to manage application and workflow state by allowing developers to model logic as actors and state machines.
✨ Create state machines visually in Stately Studio → state.new
➡️ Create state machines with the Stately Editor
🖥 Download our VS Code extension
📑 Inspired by the SCXML specification
💬 Chat on the Stately Discord Community
✍️ Browse through the many XState examples
Pick based on what you need:
@xstate/store: simple event-based state management. <1kb, great TypeScript inference, similar in spirit to Redux/Zustand. Start here if you just need a store.xstate: state machines, statecharts, actors, effects, and orchestration for complex app logic.
They work great together, but you don't need one to use the other.
Special thanks to the sponsors who support this open-source project:
Get started by forking one of these templates on CodeSandbox:
| Template | |
|---|---|
|
|
|
|
|
|
|
npm install xstateimport { createMachine, createActor, assign } from 'xstate';
// State machine
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
context: {
count: 0
},
states: {
inactive: {
on: {
TOGGLE: { target: 'active' }
}
},
active: {
entry: assign({ count: ({ context }) => context.count + 1 }),
on: {
TOGGLE: { target: 'inactive' }
}
}
}
});
// Actor (instance of the machine logic, like a store)
const toggleActor = createActor(toggleMachine);
toggleActor.subscribe((state) => console.log(state.value, state.context));
toggleActor.start();
// => logs 'inactive', { count: 0 }
toggleActor.send({ type: 'TOGGLE' });
// => logs 'active', { count: 1 }
toggleActor.send({ type: 'TOGGLE' });
// => logs 'inactive', { count: 1 }Not every app needs all the features of state machines and statecharts. @xstate/store is a separate, extremely small event-based store with first-class TypeScript inference; similar to Redux or Zustand, but with less boilerplate.
Use it on its own, or graduate to full XState machines when your logic gets more complex.
npm install @xstate/storeimport { createStore } from '@xstate/store';
const donutStore = createStore({
context: {
donuts: 0,
favoriteFlavor: 'chocolate'
},
on: {
addDonut: (context) => ({ ...context, donuts: context.donuts + 1 }),
changeFlavor: (context, event: { flavor: string }) => ({
...context,
favoriteFlavor: event.flavor
}),
eatAllDonuts: (context) => ({ ...context, donuts: 0 })
}
});
donutStore.subscribe((snapshot) => {
console.log(snapshot.context);
});
donutStore.send({ type: 'addDonut' });
// => { donuts: 1, favoriteFlavor: 'chocolate' }
donutStore.send({ type: 'changeFlavor', flavor: 'strawberry' });
// => { donuts: 1, favoriteFlavor: 'strawberry' }📖 See the @xstate/store README for React/Solid bindings, selectors, and more.
- Visually create, edit, and collaborate on state machines
- Export to many formats, including XState v5
- Test path & documentation autogeneration
- Deploy to Stately Sky
- Generate & modify machines with Stately AI
Statecharts are a formalism for modeling stateful, reactive systems. This is useful for declaratively describing the behavior of your application, from the individual components to the overall application logic.
Read 📽 the slides (🎥 video) or check out these resources for learning about the importance of finite state machines and statecharts in user interfaces:
- Statecharts - A Visual Formalism for Complex Systems by David Harel
- The World of Statecharts by Erik Mogensen
| Package | Description |
|---|---|
🤖 xstate |
Core finite state machine and statecharts library + interpreter, including graph traversal and model-based testing utilities |
🏪 @xstate/store |
Simple event-based state management (<1kb) — standalone, works with or without xstate |
⚛️ @xstate/react |
React hooks and utilities for using XState in React applications |
💚 @xstate/vue |
Vue composition functions and utilities for using XState in Vue applications |
🎷 @xstate/svelte |
Svelte utilities for using XState in Svelte applications |
🥏 @xstate/solid |
Solid hooks and utilities for using XState in Solid applications |
🔍 @statelyai/inspect |
Inspection utilities for XState |
| Code | Statechart |
|---|---|
import { createMachine, createActor } from 'xstate';
const lightMachine = createMachine({
id: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: 'yellow'
}
},
yellow: {
on: {
TIMER: 'red'
}
},
red: {
on: {
TIMER: 'green'
}
}
}
});
const actor = createActor(lightMachine);
actor.subscribe((state) => {
console.log(state.value);
});
actor.start();
// logs 'green'
actor.send({ type: 'TIMER' });
// logs 'yellow' |
Open in Stately Studio |
| Code | Statechart |
|---|---|
import { createMachine, createActor } from 'xstate';
const pedestrianStates = {
initial: 'walk',
states: {
walk: {
on: {
PED_TIMER: 'wait'
}
},
wait: {
on: {
PED_TIMER: 'stop'
}
},
stop: {}
}
};
const lightMachine = createMachine({
id: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: 'yellow'
}
},
yellow: {
on: {
TIMER: 'red'
}
},
red: {
on: {
TIMER: 'green'
},
...pedestrianStates
}
}
});
const actor = createActor(lightMachine);
actor.subscribe((state) => {
console.log(state.value);
});
actor.start();
// logs 'green'
actor.send({ type: 'TIMER' });
// logs 'yellow'
actor.send({ type: 'TIMER' });
// logs { red: 'walk' }
actor.send({ type: 'PED_TIMER' });
// logs { red: 'wait' } |
Open in Stately Studio |
| Code | Statechart |
|---|---|
import { createMachine, createActor } from 'xstate';
const wordMachine = createMachine({
id: 'word',
type: 'parallel',
states: {
bold: {
initial: 'off',
states: {
on: {
on: { TOGGLE_BOLD: 'off' }
},
off: {
on: { TOGGLE_BOLD: 'on' }
}
}
},
underline: {
initial: 'off',
states: {
on: {
on: { TOGGLE_UNDERLINE: 'off' }
},
off: {
on: { TOGGLE_UNDERLINE: 'on' }
}
}
},
italics: {
initial: 'off',
states: {
on: {
on: { TOGGLE_ITALICS: 'off' }
},
off: {
on: { TOGGLE_ITALICS: 'on' }
}
}
},
list: {
initial: 'none',
states: {
none: {
on: {
BULLETS: 'bullets',
NUMBERS: 'numbers'
}
},
bullets: {
on: {
NONE: 'none',
NUMBERS: 'numbers'
}
},
numbers: {
on: {
BULLETS: 'bullets',
NONE: 'none'
}
}
}
}
}
});
const actor = createActor(wordMachine);
actor.subscribe((state) => {
console.log(state.value);
});
actor.start();
// logs {
// bold: 'off',
// italics: 'off',
// underline: 'off',
// list: 'none'
// }
actor.send({ type: 'TOGGLE_BOLD' });
// logs {
// bold: 'on',
// italics: 'off',
// underline: 'off',
// list: 'none'
// }
actor.send({ type: 'TOGGLE_ITALICS' });
// logs {
// bold: 'on',
// italics: 'on',
// underline: 'off',
// list: 'none'
// } |
Open in Stately Studio |
| Code | Statechart |
|---|---|
import { createMachine, createActor } from 'xstate';
const Live data via GitHub REST API · Cached 30 min · Created 14 Sept 2015 |