Spawn
Sometimes invokingactors may not be flexible enough for your needs. For example, you might want to:
- Invoke child machines that last acrossseveral states
- Invoke adynamic number of actors
You can do this byspawning an actor instead of invoking. Actors created by spawning arespawning actors, and actors created with invoke areinvoking actors.
There are two ways to spawn: thespawnChild
action creator, or thespawn
helper function forassign
.
In most cases, preferspawnChild
, which causes an actor to be spawned, and can accept a configurable ID for the actor to reference it later:
createMachine({
entry:spawnChild(childMachine,{
id:'child',
}),
});
You can usespawnChild
for multiple spawned actors:
createMachine({
entry:[
spawnChild(childMachine,{ id:'child-1'}),
spawnChild(childMachine,{ id:'child-2'}),
spawnChild(childMachine,{ id:'child-3'}),
],
});
You can also use thespawn
helper function provided by theassign
action creator, which allows you to store a reference to the spawned actor (anActorRef
) in the machine'scontext
:
const parentMachine=createMachine({
entry:[
assign({
childMachineRef:({ spawn})=>spawn(childMachine,{ id:'child'}),
}),
],
});
However, if you usespawn
,make sure you remove the ActorRef fromcontext
to prevent memory leaks when the spawned actor is no longer needed:
actions:[stopChild('child'),assign({ childMachineRef:undefined})];
You canspawn
as many actors as you need:
const childMachine=createMachine({
/* ... */
});
const parentMachine=createMachine({
entry:[
assign({
childMachineRefs:({ spawn})=>[
spawn(childMachine),
spawn(childMachine),
spawn(childMachine),
],
}),
],
});
If you don’t need to keep track of a reference to the spawned actor (e.g.: for anonymous spawned actors), you can use thespawnChild
action creator. It doesnot return a reference, but indicates to the XState interpreter that a new actor should be spawned:
createMachine({
entry:spawnChild('workflow',{
id:'workflow',
}),
});
API
actions:assign({
ref:({ spawn})=>spawn(fromPromise(...),{
id:'some-id',
})
})
spawn(actorBehavior, options?)
actorBehavior
- The behavior of the actor to spawn. This can be a function, promise, observable, or callback.options
- Options for spawning the actor.id
(optional) - The ID of the actor. This is used to reference the actor in the state machine.input
(optional) - The input to pass to the actor.systemId
(optional) - A string identifing the actor, unique system-wide.
Source
- Inline:
spawn(fromPromise(...))
- Referenced:
spawn('getUser')
.provide({ actors })
Lifecycle
- Created & started when spawned
- Stopped when the machine is stopped
- Can be manually stopped
Stopping an actor
You can stop a child actor via the "stop child" action. This action is created from thestopChild(id)
action creator.
import{ setup, stopChild, fromPromise}from'xstate';
const machine=setup({
actors:{
something:fromPromise(async()=>{
// Some actor logic
return'Some response';
}),
},
}).createMachine({
context:({ spawn})=>({
something:spawn('something',{ id:'thing'}),
}),
// ...
on:{
'thing.stop':{
actions:stopChild('thing'),
},
'thing.stopFromContext':{
actions:stopChild(({ context})=> context.something),
},
},
});
Stopping a child actor doesnot remove it fromcontext
. To remove it from context, use theassign(...)
action creator:
import{ setup, stopChild}from'xstate';
const machine=setup({
// ...
}).createMachine({
context:({ spawn})=>({
something:spawn('something',{ id:'thing'}),
}),
// ...
on:{
'thing.stop':{
actions:[stopChild('thing'),assign({ something:undefined})],
},
},
});
Spawn and TypeScript
XState v5 requires TypeScript version 5.0 or greater.
For best results, use the latest TypeScript version.Read more about XState and TypeScript
Coming soon
Spawn cheatsheet
Coming soon