XState is a very useful front-end state library, but the official website documents are only in English. In order to facilitate more people to understand and increase the reading experience, I have translated the Chinese version here.
- Warehouse address (welcome to Star
) : github.com/lecepin/xst…
- IO /xstate-docs docs: lecepin.github.
Due to my limited level, coupled with a short translation cycle, mistakes are inevitable, welcome readers’ criticism and correction.
JavaScript state machines and state diagrams
Finite state machines and state graphs in JavaScript and TypeScript for the modern Web.
Still not familiar with state machines and state diagrams? Read our introduction.
complies with the SCXML specification
Talk to us at at Stately Discord Community
package
xstate
– Finite state machine and state graph core library + interpreter@xstate/ FSM – Minimum finite State library
@xstate/ graph-XState’s Graph traversal utility kit
@xstate/react – Use xstate’s React Hooks and utility kit in react applications
@xstate/vue – VUE composite functions and utility kits for using xstate in VUE applications
@xstate/svelte – Svelte utility kit for using XState in Svelte applications
@xstate/test – Utility kit for model-based testing (using Xstate)
@xstate/inspect – Xstate’s inspection utility kit
The template
Start by creating one of these templates on CodeSandbox:
- XState Template – No framework
- XState + TypeScript Template – No framework
- XState + React Template
- XState + React + TypeScript Template
- XState + Vue Template
- XState + Vue 3 Template
- XState + Svelte Template
Super quick to learn
npm install xstate
Copy the code
import { createMachine, interpret } from 'xstate';
// Stateless state machine definition
// machine.transition(...) Is a pure function used by the interpreter.
const toggleMachine = createMachine({
id: 'toggle'.initial: 'inactive'.states: {
inactive: {
on: {
TOGGLE: { target: 'active'}}},active: {
on: {
TOGGLE: { target: 'inactive'}}}}});// State 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'
Copy the code
Promise the sample
view the visualization at stately. Ai /viz
import { createMachine, interpret, assign } from 'xstate';
const fetchMachine = createMachine({
id: 'Dog API'.initial: 'idle'.context: {
dog: null
},
states: {
idle: {
on: {
FETCH: { target: 'loading'}}},loading: {
invoke: {
id: 'fetchDog'.src: (context, event) = >
fetch('https://dog.ceo/api/breeds/image/random').then((data) = >
data.json()
),
onDone: {
target: 'resolved'.actions: assign({
dog: (_, event) = > event.data
})
},
onError: {
target: 'rejected'}},on: {
CANCEL: { target: 'idle'}}},rejected: {
on: {
FETCH: { target: 'loading'}}},resolved: {
type: 'final'}}});const dogService = interpret(fetchMachine)
.onTransition((state) = > console.log(state.value))
.start();
dogService.send({ type: 'FETCH' });
Copy the code
- Visualization tool
- Why is that?
- Finite state machine
- Layered (nested) state machines
- Parallel state machine
- The historical status
Visualization tool
Visualize, simulate, and share your state maps in XState Viz!
Why is that?
A state diagram is a way of modeling a stateful interactive system. From individual components to entire application logic, this is useful for declaratively describing the behavior of an application.
Read the slide show (
video) or check out these resources to understand the importance of finite state machines and state diagrams in UI:
- State diagrams – A visual representation of a complex system by David Harel
- The World of state diagrams by Erik Mogensen
- Pure UI by Guillermo Rauch
- Pure UI control by Adam Solove
- Spectrum – State Graph Community (for XState specific issues, use GitHub for discussion)
Finite state machine
import { createMachine } from 'xstate';
const lightMachine = createMachine({
id: 'light'.initial: 'green'.states: {
green: {
on: {
TIMER: { target: 'yellow'}}},yellow: {
on: {
TIMER: { target: 'red'}}},red: {
on: {
TIMER: { target: 'green'}}}}});const currentState = 'green';
const nextState = lightMachine.transition(currentState, { type: 'TIMER' })
.value;
// => 'yellow'
Copy the code
Layered (nested) state machines
import { createMachine } from 'xstate';
const pedestrianStates = {
initial: 'walk'.states: {
walk: {
on: {
PED_TIMER: { target: 'wait'}}},wait: {
on: {
PED_TIMER: { target: 'stop'}}},stop: {}}};const lightMachine = createMachine({
id: 'light'.initial: 'green'.states: {
green: {
on: {
TIMER: { target: 'yellow'}}},yellow: {
on: {
TIMER: { target: 'red'}}},red: {
on: {
TIMER: { target: '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'
// }
Copy the code
Object symbols 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'
Copy the code
Parallel state machine
import { createMachine } from 'xstate';
const wordMachine = createMachine({
id: 'word'.type: 'parallel'.states: {
bold: {
initial: 'off'.states: {
on: {
on: {
TOGGLE_BOLD: { target: 'off'}}},off: {
on: {
TOGGLE_BOLD: { target: 'on'}}}}},underline: {
initial: 'off'.states: {
on: {
on: {
TOGGLE_UNDERLINE: { target: 'off'}}},off: {
on: {
TOGGLE_UNDERLINE: { target: 'on'}}}}},italics: {
initial: 'off'.states: {
on: {
on: {
TOGGLE_ITALICS: { target: 'off'}}},off: {
on: {
TOGGLE_ITALICS: { target: 'on'}}}}},list: {
initial: 'none'.states: {
none: {
on: {
BULLETS: { target: 'bullets' },
NUMBERS: { target: 'numbers'}}},bullets: {
on: {
NONE: { target: 'none' },
NUMBERS: { target: 'numbers'}}},numbers: {
on: {
BULLETS: { target: 'bullets' },
NONE: { target: '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'
// }
Copy the code
The historical status
import { createMachine } from 'xstate';
const paymentMachine = createMachine({
id: 'payment'.initial: 'method'.states: {
method: {
initial: 'cash'.states: {
cash: {
on: {
SWITCH_CHECK: { target: 'check'}}},check: {
on: {
SWITCH_CASH: { target: 'cash'}}},hist: { type: 'history'}},on: {
NEXT: { target: 'review'}}},review: {
on: {
PREVIOUS: { target: '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' }
Copy the code