| title | Context |
|---|---|
| description | Store and update data used by a machine actor. |
Context stores data that does not determine the current state by itself.
const machine = createMachine({ context: { count: 0, name: '' } });context: ({ input }: { input: { name: string } }) => ({
count: 0,
name: input.name
})Return a context object from a transition function. XState merges it into the current context at the top level, so keys you omit keep their current values:
// context before: { count: 0, name: 'Ada' }
increment: ({ context }) => ({ context: { count: context.count + 1 } })
// context after: { count: 1, name: 'Ada' }The merge is shallow. A nested object in the returned patch replaces the current value of that key; spread the nested object yourself to keep its other fields.
Context patches returned by entry functions follow the same merge rules. Previously captured snapshots keep their original context.
While computing a transition, read the callback's context argument. self.getSnapshot() returns the last committed snapshot until the computation finishes.
Do not mutate the current context. Keep resources that cannot be serialized outside context.
In development builds, XState deep-freezes the plain objects and arrays in each snapshot's context, so a mutation such as snapshot.context.count = 1 throws a TypeError in strict mode. Freezing also applies to objects you place into context, including restored snapshot context. Actor refs, class instances, Map, Set, Date and other non-plain objects are not frozen. Production builds do not freeze context.
Use context for supporting data, not hidden state. An order can store its items and total in context while its current status stays in states such as editing, paying and complete.
Input creates context for each actor instance. The same machine can run one upload for report.pdf and another for photo.jpg without closing over either file.
Context is inferred from its initial value or the return value of a context initializer. Without schemas.context, createMachine({ context: () => ({ count: 0 }) }) still gives snapshot.context.count the type number. The initializer’s spawn returns a typed actor ref. Use a context schema when you need a wider or shared type.
With schemas.context, TypeScript rejects reads of undeclared context keys and patches that contain only undeclared keys. Callbacks and actor snapshots retain the schema's field types, including after snapshot.matches(...) narrows a state. To accept arbitrary keys, declare an index signature in the context schema.
Declare a state-level schemas.context to narrow context in that state.
For example, a loaded state can require user: string while the root
context allows user: string | null. snapshot.matches('loaded') then
narrows the context type. See Typestates.
context: { count: 0 }
on: {
increment: ({ context }) => ({
context: { ...context, count: context.count + 1 }
})
}