Final states
A final state is a state that represents the completion or successful termination of a machine. It is defined by the type: 'final'
property on a state node:
import { createMachine, interpret } from 'xstate';
const feedbackMachine = createMachine({
initial: 'prompt',
states: {
prompt: {
/* ... */
},
thanks: {
/* ... */
},
closed: {
type: 'final',
},
// ...
},
on: {
'feedback.close': {
target: '.closed',
},
},
});
When a machine reaches the final state, it can no longer receive any events, and anything running inside it is canceled and cleaned up. The box with a surrounding border icon represents the final state.
A machine can have multiple final states or no final states.
- A state machine can have zero or more final states. Some machines may run indefinitely and not need to terminate.
- Final states can have
output
data, which is sent to the parent machine when the machine terminates. - When a machine reaches a top-level final state, it terminates.
- Final states cannot have transitions
Using final states in Stately Studio
In the video player above, Stopped is the final child state in the Opened state. When the video player is Stopped, the video player moves to its Closed state.
Make a state a final state
First, select the state you want to set as the final state.
Using the quick actions menu
- Right-click the state to bring up the quick actions menu.
- Choose Final from the Type options.
Using the State details panel
- Select the state you want to set as the final state.
- Open the State details panel from the right tool menu.
- Choose Final from the Type dropdown menu.
Top-level final states
A top-level final state is a final state that is a direct child state of the machine. When the machine reaches a top-level final state, the machine will terminate. When a machine terminates, it can no longer receive events nor transition.
Child final states
When a child final state of a compound state is reached, that compound state is considered "done". The onDone
transition of that compound state is taken.
Final states in parallel states
When all regions of a parallel state are "done", the parallel state is considered "done". The onDone
transition of the parallel state is taken.
In this example, the preparation
state is a parallel state with two regions: beans
and water
. When both regions are done, the preparation
state is done, and the brewing
state is entered.
import { createMachine, interpret } from 'xstate';
const coffeeMachine = createMachine({
initial: 'preparation',
states: {
preparation: {
type: 'parallel',
states: {
beans: {
initial: 'grinding',
states: {
grinding: {
on: {
grindingComplete: 'ground',
},
},
ground: {
type: 'final',
},
},
},
water: {
initial: 'heating',
states: {
heating: {
always: {
guard: 'waterBoiling',
target: 'heated',
},
},
heated: {
type: 'final',
},
},
},
},
onDone: 'brewing',
},
brewing: {},
},
});
Output
When a machine reaches its top-level final state, it can produce output data. You can specify this output data in the .output
property of the top-level final state:
import { createMachine, interpret } from 'xstate';
const currencyMachine = createMachine({
// ...
states: {
converting: {
// ...
},
converted: {
type: 'final',
output: ({ context }) => ({
amount: context.amount,
currency: context.currency,
}),
},
},
});
const currencyActor = interpret(currencyMachine, {
input: {
amount: 10,
fromCurrency: 'USD',
toCurrency: 'EUR',
},
});
currencyActor.onDone(() => {
console.log(currencyActor.getSnapshot().output);
// logs e.g. { amount: 12, currency: 'EUR' }
});
.output
can also be a static value
TypeScript
Coming soon
Cheatsheet
Coming soon