Delayed (after) transitions
Delayed transitions are transitions that only happen after a set amount of time. Delayed transitions are handy for building timeouts and intervals into your application logic. If another event occurs before the end of the timer, the transition doesn’t complete.
Delayed transitions are defined on the after
property in milliseconds. They are often referred to as “after” transitions.
import { createMachine } from 'xstate';
const pushTheButtonGame = createMachine({
initial: 'waitingForButtonPush',
states: {
waitingForButtonPush: {
after: {
5000: {
target: 'timedOut',
actions: 'logThatYouGotTimedOut',
},
},
on: {
PUSH_BUTTON: {
actions: 'logSuccess',
target: 'success',
},
},
},
success: {},
timedOut: {},
},
});
Delays
You can define delays in a few ways: inlined, referenced, and as an expression.
Inlined delays
You can define an inlined delay by specifying the delay time (in milliseconds) directly:
const machine = createMachine({
initial: 'idle',
states: {
idle: {
after: {
1000: { target: 'nextState' },
},
},
nextState: {},
},
});
This will transition to the nextState
state after 1000ms.
Referenced delays
You can also define referenced delays by specifying a string delay key, and providing the actual delay time separately.
For example:
const machine = createMachine(
{
initial: 'idle',
states: {
idle: {
after: {
timeout: { target: 'nextState' },
},
},
nextState: {},
},
},
{
delays: {
timeout: 1000,
},
},
);
Lifecycle
Delayed transition timers are canceled when the state is exited.
Testing
- Simulated clock
TypeScript
You can strongly type the delays
of your machine in the types.delays
property of the machine config.
const machine = createMachine({
types: {} as {
delays: 'shortTimeout' | 'longTimeout' | 'eventually';
// ...
},
// ...
after: {
// Autocompleted
shortTimeout: {
/* ... */
},
},
on: {
someEvent: {
actions: raise(
{ type: 'anotherEvent' },
{
// Autocompleted
delay: 'eventually',
},
),
},
},
});
You can also setup the delay using the setup()
function:
import { setup } from 'xstate';
const machine = setup({
delays: {
shortTimeout: 1000,
longTimeout: 5000,
eventually: 10_000
}
}).createMachine({
after: {
shortTimeout: {/* ... */}
}
});
Cheatsheet
Use our XState delayed transitions cheatsheet below to get started quickly.
createMachine({
after: {
DELAY: {
/* ... */
},
},
}).provide({
delays: {
DELAY: 1000, // or expression
},
});