- @xstate/solid@0.2.3Latest
- @xstate/store@2.5.0
- @xstate/store@2.4.0
- xstate@5.18.0
- @xstate/store@2.3.0
- @xstate/store@2.2.1
- xstate@5.17.4
- xstate@5.17.3
- xstate@5.17.2
- @xstate/store@2.1.0
- xstate@5.17.1
- xstate@5.17.0
- xstate@5.16.0
- xstate@5.15.0
- xstate@5.14.0
- @xstate/store@1.0.0
- xstate@5.13.2
- xstate@5.13.1
- @xstate/store@0.0.5
- @xstate/graph@2.0.0
- @xstate/store@0.0.4
- xstate@5.13.0
- xstate@5.12.0
- @xstate/vue@3.1.2
- @xstate/svelte@3.0.3
- @xstate/react@4.1.1
- @xstate/store@0.0.3
- xstate@5.10.0
- @xstate/store@0.0.2
- xstate@5.9.1
- xstate@5.9.0
- xstate@5.8.2
- xstate@5.8.1
- @xstate/vue@3.1.1
- xstate@5.8.0
- @xstate/solid@0.2.0
- xstate@5.7.1
- xstate@5.7.0
- @xstate/react@4.1.0
- @xstate/vue@3.1.0
- xstate@5.6.2
- xstate@5.6.1
- xstate@5.6.0
- @xstate/react@4.0.3
- xstate@5.5.2
- @xstate/graph@2.0.0-beta.6
- @xstate/test@1.0.0-beta.5
- xstate@5.5.1
- xstate@5.5.0
- xstate@5.4.0
- @xstate/vue@3.0.2
- xstate@5.3.1
- @xstate/svelte@3.0.1
- @xstate/vue@3.0.1
- xstate@5.3.0
- xstate@5.2.1
- xstate@5.2.0
- @xstate/react@4.0.1
- xstate@5.1.0
- xstate@5.0.2
- xstate@5.0.1
- @xstate/react@4.0.0-beta.12
- xstate@5.0.0-beta.54
- xstate@5.0.0-beta.53
- xstate@5.0.0-beta.52
- xstate@5.0.0-beta.50
- xstate@5.0.0-beta.49
- xstate@5.0.0-beta.48
- xstate@5.0.0-beta.47
- xstate@5.0.0-beta.46
- xstate@5.0.0-beta.45
- xstate@5.0.0-beta.44
- xstate@5.0.0-beta.43
- @xstate/vue@3.0.0-beta.6
- xstate@5.0.0-beta.42
- xstate@5.0.0-beta.41
- @xstate/react@4.0.0-beta.11
- xstate@5.0.0-beta.40
- xstate@5.0.0-beta.39
- xstate@5.0.0-beta.38
- xstate@5.0.0-beta.37
- xstate@4.38.3
- xstate@5.0.0-beta.36
- xstate@5.0.0-beta.35
- xstate@5.0.0-beta.34
- xstate@5.0.0-beta.33
- xstate@5.0.0-beta.32
- xstate@5.0.0-beta.31
- @xstate/test@1.0.0-beta.4
- @xstate/graph@2.0.0-beta.5
- xstate@5.0.0-beta.30
- @xstate/react@4.0.0-beta.10
- xstate@5.0.0-beta.29
- xstate@5.0.0-beta.28
- @xstate/vue@3.0.0-beta.5
- @xstate/react@4.0.0-beta.9
- xstate@5.0.0-beta.27
- @xstate/test@1.0.0-beta.3
- @xstate/graph@2.0.0-beta.4
- @xstate/test@1.0.0-beta.2
- @xstate/graph@2.0.0-beta.3
- xstate@5.0.0-beta.26
- xstate@5.0.0-beta.25
- xstate@5.0.0-beta.24
- xstate@5.0.0-beta.23
- xstate@5.0.0-beta.22
- xstate@5.0.0-beta.21
- xstate@5.0.0-beta.20
- xstate@4.38.2
- xstate@5.0.0-beta.19
- xstate@4.38.1
- xstate@5.0.0-beta.17
- xstate@5.0.0-beta.16
- @xstate/react@4.0.0-beta.7
- xstate@5.0.0-beta.15
- xstate@4.38.0
- @xstate/fsm@2.1.0
- xstate@5.0.0-beta.14
- @xstate/react@4.0.0-beta.6
- @xstate/vue@3.0.0-beta.3
- @xstate/immer@0.3.3
- @xstate/fsm@2.0.1
- @xstate/react@4.0.0-beta.5
- xstate@5.0.0-beta.13
- xstate@5.0.0-beta.11
- xstate@5.0.0-beta.10
- @xstate/react@4.0.0-beta.4
- xstate@5.0.0-beta.9
- @xstate/graph@2.0.0-alpha.2
- xstate@4.37.2
- xstate@5.0.0-beta.8
- xstate@5.0.0-alpha.6
- xstate@5.0.0-alpha.5
- xstate@5.0.0-alpha.4
- @xstate/fsm@3.0.0-alpha.1
- @xstate/react@4.0.0-alpha.2
- xstate@5.0.0-alpha.3
- xstate@5.0.0-alpha.2
- xstate@4.37.1
- @xstate/test@1.0.0-alpha.1
- @xstate/graph@2.0.0-alpha.1
- @xstate/inspect@0.8.0
- @xstate/solid@0.1.3
- xstate@4.37.0
- @xstate/immer@0.3.2
- @xstate/react@3.2.1
- xstate@4.36.0
- @xstate/react@3.2.0
- @xstate/solid@0.1.2
- @xstate/react@3.1.2
- @xstate/solid@0.1.1
- xstate@4.35.4
- @xstate/react@3.0.2
- xstate@4.35.2
- xstate@4.35.1
- @xstate/svelte@2.0.1
- xstate@4.34.0
- xstate@4.33.6
- xstate@4.33.5
- xstate@4.33.4
- xstate@4.33.3
- xstate@4.33.2
- xstate@4.33.1
- xstate@4.33.0
- @xstate/react@3.0.1
- @xstate/test@1.0.0-alpha.0
- @xstate/graph@2.0.0-alpha.0
- @xstate/react@4.0.0-alpha.0
- xstate@5.0.0-alpha.0
- @xstate/vue@3.0.0-alpha.0
- xstate@4.32.1
- @xstate/svelte@2.0.0
- xstate@4.32.0
- @xstate/inspect@0.7.0
- xstate@4.30.6
- @xstate/inspect@0.6.4
- xstate@4.30.5
- xstate@4.30.4
- xstate@4.30.2
- @xstate/fsm@1.6.5
- xstate@4.30.1
- xstate@4.30.0
- xstate@4.28.1
- @xstate/inspect@0.6.1
- xstate@4.28.0
- xstate@4.27.0
- @xstate/fsm@1.6.3
- @xstate/inspect@0.6.0
- xstate@4.26.1
- @xstate/inspect@0.5.2
- @xstate/react@1.6.3
- xstate@4.26.0
- @xstate/react@1.6.2
- xstate@4.25.0
- xstate@4.24.1
- xstate@4.24.0
- @xstate/svelte@0.2.0
- xstate@4.23.4
- @xstate/fsm@1.6.2
- @xstate/react@1.6.1
- xstate@4.23.3
- xstate@4.23.1
- xstate@4.23.0
- @xstate/vue@0.8.0
- @xstate/react@1.5.1
- xstate@4.22.0
- @xstate/react@1.5.0
- @xstate/vue@0.7.0
- xstate@4.20.2
- @xstate/react@1.4.0
- @xstate/vue@0.6.0
- xstate@4.20.1
- xstate@4.20.0
- @xstate/react@1.3.4
- @xstate/fsm@1.6.1
- v1.19.1
- xstate@4.19.2
- xstate@4.19.1
- @xstate/react@1.3.3
- xstate@4.19.0
- @xstate/react@1.3.2
- xstate@4.18.0
- xstate@4.17.1
- xstate@4.17.0
- @xstate/vue@0.5.0
- @xstate/react@1.3.1
- @xstate/react@1.3.0
- xstate@4.16.2
- @xstate/fsm@1.6.0
- xstate@4.16.1
- @xstate/immer@0.2.0
- @xstate/svelte@0.1.0
- xstate@4.16.0
- xstate@4.15.4
- @xstate/inspect@0.4.1
- @xstate/inspect@0.4.0
- xstate@4.15.3
- @xstate/vue@0.4.0
- @xstate/react@1.2.2
- xstate@4.15.2
- @xstate/react@1.2.1
- @xstate/react@1.2.0
- @xstate/inspect@0.3.0
- xstate@4.15.1
- xstate@4.15.0
- @xstate/react@1.1.0
- @xstate/graph@1.3.0
- @xstate/fsm@1.5.2
- xstate@4.14.1
- @xstate/react@1.0.3
JavaScript state machines and statecharts
JavaScript and TypeScript finite state machines and statecharts for the modern web.
π Read the documentation π Adheres to the SCXML specification.
Packages
- π€
xstate
- Core finite state machine and statecharts library + interpreter - π
@xstate/graph
- Graph traversal utilities for XState - βοΈ
@xstate/react
- React hooks and utilities for using XState in React applications - β
@xstate/test
- Model-based testing utilities for XState
Super quick start
npm install xstate
import { createMachine, interpret } from 'xstate';
// Stateless machine definition
// machine.transition(...) is a pure function used by the interpreter.
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: { on: { TOGGLE: 'active' } },
active: { on: { TOGGLE: 'inactive' } }
}
});
// Machine instance with internal state
const toggleService = interpret(toggleMachine)
.onTransition((state) => console.log(state.value))
.start();
// => 'inactive'
toggleService.send({ type: 'TOGGLE' });
// => 'active'
toggleService.send({ type: 'TOGGLE' });
// => 'inactive'
- Visualizer
- Why? (info about statecharts)
- Installation
- Finite State Machines
- Hierarchical (Nested) State Machines
- Parallel State Machines
- History States
Visualizer
Visualize, simulate, and share your statecharts in XState Viz!
Why?
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
- Pure UI by Guillermo Rauch
- Pure UI Control by Adam Solove
- Stately Discord chat about anything related to statecharts and XState
- GitHub Discussions
Finite State Machines
import { createMachine } from 'xstate';
const lightMachine = createMachine({
id: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: 'yellow'
}
},
yellow: {
on: {
TIMER: 'red'
}
},
red: {
on: {
TIMER: 'green'
}
}
}
});
const currentState = 'green';
const nextState = lightMachine.transition(currentState, {
type: 'TIMER'
}).value;
// => 'yellow'
Hierarchical (Nested) State Machines
import { createMachine } 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 currentState = 'yellow';
const nextState = lightMachine.transition(currentState, {
type: 'TIMER'
}).value;
// => {
// red: 'walk'
// }
lightMachine.transition('red.walk', { type: 'PED_TIMER' }).value;
// => {
// red: 'wait'
// }
Object notation for hierarchical states:
// ...
const waitState = lightMachine.transition(
{ red: 'walk' },
{ type: 'PED_TIMER' }
).value;
// => { red: 'wait' }
lightMachine.transition(waitState, { type: 'PED_TIMER' }).value;
// => { red: 'stop' }
lightMachine.transition({ red: 'stop' }, { type: 'TIMER' }).value;
// => 'green'
Parallel State Machines
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 boldState = wordMachine.transition('bold.off', {
type: 'TOGGLE_BOLD'
}).value;
// {
// bold: 'on',
// italics: 'off',
// underline: 'off',
// list: 'none'
// }
const nextState = wordMachine.transition(
{
bold: 'off',
italics: 'off',
underline: 'on',
list: 'bullets'
},
{ type: 'TOGGLE_ITALICS' }
).value;
// {
// bold: 'off',
// italics: 'on',
// underline: 'on',
// list: 'bullets'
// }
History States
const paymentMachine = createMachine({
id: 'payment',
initial: 'method',
states: {
method: {
initial: 'cash',
states: {
cash: { on: { SWITCH_CHECK: 'check' } },
check: { on: { SWITCH_CASH: 'cash' } },
hist: { type: 'history' }
},
on: { NEXT: 'review' }
},
review: {
on: { PREVIOUS: 'method.hist' }
}
}
});
const checkState = paymentMachine.transition('method.cash', {
type: 'SWITCH_CHECK'
});
// => State {
// value: { method: 'check' },
// history: State { ... }
// }
const reviewState = paymentMachine.transition(checkState, { type: 'NEXT' });
// => State {
// value: 'review',
// history: State { ... }
// }
const previousState = paymentMachine.transition(reviewState, {
type: 'PREVIOUS'
}).value;
// => { method: 'check' }
Sponsors
Huge thanks to the following companies for sponsoring xstate
. You can sponsor further xstate
development on OpenCollective.