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, createActor } 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
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, createActor } 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 machine:
import { createMachine, createActor } from 'xstate';
const currencyMachine = createMachine({
// ...
states: {
converting: {
// ...
},
converted: {
type: 'final',
},
},
output: ({ context }) => ({
amount: context.amount,
currency: context.currency,
}),
});
const currencyActor = createActor(currencyMachine, {
input: {
amount: 10,
fromCurrency: 'USD',
toCurrency: 'EUR',
},
});
currencyActor.subscribe({
complete() {
console.log(currencyActor.getSnapshot().output);
// logs e.g. { amount: 12, currency: 'EUR' }
},
});
The .output
property can also be a static value:
import { createMachine, createActor } from 'xstate';
const processMachine = createMachine({
// ...
output: {
message: 'Process completed.',
},
});
TypeScript​
Coming soon
Cheatsheet​
Coming soon