Other state attributes
States can have various other attributes, most of which are useful for narrower cases.
State tags​
State nodes can have tags, a list of strings that help describe the state node. Tags can be useful when categorizing different state nodes. For example, you can signify which state nodes represent “loading data” using a "loading"
tag and determine if a state contains those tagged state nodes with state.hasTag(tag)
:
import { createMachine, interpret } from 'xstate';
const machine = createMachine({
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loadingUser',
},
},
loadingUser: {
tags: ['loading'],
},
loadingFriends: {
tags: ['loading'],
},
editing: {},
},
});
const actor = interpret(machine).start();
actor.state.hasTag('loading'); // false
actor.send('FETCH');
actor.state.hasTag('loading'); // true
Using tags can help you write more concise code. Instead of matching each actor individually:
import { createMachine, interpret } from 'xstate';
const machine = createMachine({
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loadingUser',
},
},
loadingUser: {
tags: ['loading'],
},
loadingFriends: {
tags: ['loading'],
},
editing: {},
},
});
const actor = interpret(machine).start();
const isLoading =
actor.state.matches('loadingUser') || actor.state.matches('loadingFriends');
You can group the actors by tag:
import { createMachine, interpret } from 'xstate';
const machine = createMachine({
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loadingUser',
},
},
loadingUser: {
tags: ['loading'],
},
loadingFriends: {
tags: ['loading'],
},
editing: {},
},
});
const actor = interpret(machine).start();
const isLoading = actor.state.hasTag('loading');
Defining tags​
- Tags can be specified via an array, as
tag: ['tag1', 'tag2']
, or by a single string:tag: 'tag1'
. - Tags can be made type-safe in TypeScript by using typegen.
State meta​
You can attach arbitrary data to any state by specifying it as meta
on the state node:
import { createMachine, interpret } from 'xstate';
const fetchMachine = createMachine({
initial: 'pending',
states: {
pending: {
on: {
UNKNOWN_ERROR: 'errored',
},
after: {
5000: 'timedOut',
},
},
errored: {
meta: {
error: 'An unknown error occurred',
},
},
timedOut: {
meta: {
error: 'Timeout error!',
},
},
},
});
You can store anything in the meta
attribute; XState doesn’t monitor it or do anything with its contents.
The current state of the machine collects the meta
data of all of the state nodes, represented by the state value, and places them on an object where:
- The keys are the state node IDs
- The values are the state node
meta
values
For instance, if the machine above is in the timedOut
state, the meta
will be an object with the following shape:
{
timedOut: {
alert: 'Timeout error!'
},
}
State descriptions​
You can add descriptive text to states with the description
attribute.
This text is used by the Visualizer and the Studio Editor to make the diagrams more descriptive.
import { createMachine } from 'xstate';
const machine = createMachine({
initial: 'pending',
description: `A machine that waits for something to happen, then completes`,
states: {
pending: {
on: {
FINISHED: 'complete',
},
description: `Waiting...`,
},
complete: {
description: `Done!`,
},
},
});