Context
In XState, context
is how you store data in a state machine actor.
The context
property is available in all states and used to store data relevant to an actor. The context
object is immutable, so you cannot directly modify it. Instead, for state machine logic, you can use the assign(...)
action to update context
.
The context
property is optional; if the state machine only specifies finite states and no external contextual data, it may not need context
.
import { createMachine, createActor } from 'xstate';
const feedbackMachine = createMachine({
// Initialize the state machine with context
context: {
feedback: 'Some feedback',
},
});
const feedbackActor = createActor(feedbackMachine);
feedbackActor.subscribe((state) => {
console.log(state.context.feedback);
});
feedbackActor.start();
// logs 'Some feedback'
Initial contextβ
Set the initial context of a machine in the context
property of the machine config:
import { createMachine } from 'xstate';
const feedbackMachine = createMachine({
context: {
feedback: 'Some feedback',
rating: 5,
// other properties
},
});
The object you pass to context
will be the initial context
value for any actor created from this machine.
Lazy initial contextβ
Context can be initialized lazily by passing a function that returns the initial context
value:
const feedbackMachine = createMachine({
context: () => ({
feedback: 'Some feedback',
createdAt: Date.now(),
}),
});
const feedbackActor = createActor(feedbackMachine).start();
console.log(feedbackActor.getSnapshot().context.createdAt);
// logs the current timestamp
Lazy initial context is evaluated per actor, so each actor will have its own context
object.
Inputβ
You can provide input data to a machineβs initial context
by passing an input
property to the createActor(machine, { input })
function and using the input
property from the first argument in the context
function:
import { setup, createActor } from 'xstate';
const feedbackMachine = setup({
types: {
context: {} as {
feedback: string;
rating: number;
},
input: {} as {
defaultRating: number;
},
},
}).createMachine({
context: ({ input }) => ({
feedback: '',
rating: input.defaultRating,
}),
});
const feedbackActor = createActor(feedbackMachine, {
input: {
defaultRating: 5,
},
}).start();
console.log(feedbackActor.getSnapshot().context.rating);
// logs 5
Learn more about input.
Updating context with assign(...)
β
Use the assign(...)
action in a transition to update context:
import { createMachine, assign, createActor } from 'xstate';
const feedbackMachine = createMachine({
context: {
feedback: 'Some feedback',
},
on: {
'feedback.update': {
actions: assign({
feedback: ({ event }) => event.feedback,
}),
},
},
});
const feedbackActor = createActor(feedbackMachine);
feedbackActor.subscribe((state) => {
console.log(state.context.feedback);
});
feedbackActor.start();
// logs 'Some feedback'
feedbackActor.send({
type: 'feedback.update',
feedback: 'Some other feedback',
});
// logs 'Some other feedback'
Context and TypeScriptβ
You can strongly type the context
of your machine in the types.context
property of the actor setup..
import { setup } from 'xstate';
const machine = setup({
types: {} as {
context: {
feedback: string;
rating: number;
};
},
}).createMachine({
// Initial context
context: {
feedback: '',
rating: 5,
},
entry: ({ context }) => {
context.feedback; // string
context.rating; // number
},
});
Context cheatsheetβ
Use our XState context cheatsheet below to get started quickly.
Cheatsheet: initial contextβ
const machine = createMachine({
context: {
feedback: '',
},
});
Cheatsheet: lazy initial contextβ
const machine = createMachine({
context: () => ({
feedback: '',
createdAt: Date.now(),
}),
});
Cheatsheet: updating context with assign(...)
β
const machine = createMachine({
context: {
feedback: '',
},
on: {
'feedback.update': {
actions: assign({
feedback: ({ event }) => event.feedback,
}),
},
},
});
Cheatsheet: inputβ
import { setup, createActor } from 'xstate';
const feedbackMachine = setup({
types: {
context: {} as {
feedback: string;
rating: number;
},
input: {} as {
defaultRating: number;
},
},
}).createMachine({
context: ({ input }) => ({
feedback: '',
rating: input.defaultRating,
}),
});
const feedbackActor = createActor(feedbackMachine, {
input: {
defaultRating: 5,
},
}).start();