State input
Pass typed data to a state when it is entered.
XState v6 is in alpha
A state can declare an input schema. Transitions that target the state pass input alongside target, and the state's own functions read it from their arguments.
Declare the schema in setup(...):
const uploadSetup = setup({
states: {
idle: {},
uploading: {
schemas: { input: z.object({ fileName: z.string() }) }
}
}
});Then pass input from the transition:
const uploadMachine = uploadSetup.createMachine({
initial: 'idle',
states: {
idle: {
on: {
upload: { target: 'uploading', input: { fileName: 'report.pdf' } }
}
},
uploading: {
entry: ({ input }) => console.log(input.fileName)
}
}
});State input is available to the target state's entry, exit, on, after, timeout, onTimeout and output functions. It persists across self-transitions and is replaced the next time the state is entered.
Computing input
A transition function can compute input from context and the event.
idle: {
on: {
upload: ({ context, event }) => ({
target: 'uploading',
input: { fileName: event.fileName, token: context.authToken }
})
}
}Initial state input
The initial property accepts an object form so the initial state receives input too. A plain string is still used when the state needs none.
uploadSetup.createMachine({
initial: { target: 'uploading', input: { fileName: 'report.pdf' } },
states: {
uploading: { entry: ({ input }) => console.log(input.fileName) }
}
});Nested states work the same way: a parent's initial passes input to its child.
Reading input from a snapshot
snapshot.getInputs() returns the current inputs keyed by state node ID.
const inputs = actor.getSnapshot().getInputs();
inputs['(machine).uploading']; // { fileName: 'report.pdf' }Use state input for data that belongs to one state rather than to the whole machine:
- a checkout
payingstate that needs the selected payment method - a media player
bufferingstate that needs the track being loaded - a form
submittingstate that needs the validated values
Warning: State input is not actor input, which is passed once when an actor is created, and it is not action
params, which belong to a named action call. State input belongs to a state and is provided by whichever transition enters it.
TypeScript
Input is typed by the state's schemas.input. Transitions targeting the state require a matching input, and ({ input }) is typed inside that state's functions. Modular state configs created with setup(...).createStateConfig(...) are typed the same way. See setup and provide.
State input cheatsheet
const s = setup({
states: { loading: { schemas: { input: z.object({ id: z.string() }) } } }
});
s.createMachine({
initial: { target: 'loading', input: { id: 'a1' } },
states: {
loading: {
entry: ({ input }) => input.id,
on: { retry: { target: 'loading', input: { id: 'a2' } } }
}
}
});
actor.getSnapshot().getInputs();