Major Changes
-
#3837
61553600b
Thanks @davidkpiano! - Actors are now always part of a "system", which is a collection of actors that can communicate with each other. Systems are implicitly created, and can be used to get and set references to any actor in the system via thesystemId
prop:const machine = createMachine({ // ... invoke: { src: emailMachine, // Registers `emailMachine` as `emailer` on the system systemId: 'emailer' } });
const machine = createMachine({ // ... entry: assign({ emailer: (ctx, ev, { spawn }) => spawn(emailMachine, { systemId: 'emailer' }) }) });
Any invoked/spawned actor that is part of a system will be able to reference that actor:
const anotherMachine = createMachine({ // ... entry: sendTo( (ctx, ev, { system }) => { return system.get('emailer'); }, { type: 'SEND_EMAIL', subject: 'Hello', body: 'World' } ) });
Each top-level
interpret(...)
call creates a separate implicit system. In this example example,actor1
andactor2
are part of different systems and are unrelated:// Implicit system const actor1 = interpret(machine).start(); // Another implicit system const actor2 = interpret(machine).start();
-
#3911
d638a0001
Thanks @davidkpiano! - Theself
actor reference is now available in all action metas. This makes it easier to reference the "self"ActorRef
so that actions such assendTo
can include it in the event payload:// Sender actions: sendTo('somewhere', (ctx, ev, { self }) => ({ type: 'EVENT', ref: self })), // ... // Responder actions: sendTo((ctx, ev) => ev.ref, ...)
-
#3743
30c561e94
Thanks @davidkpiano! - Restoring persisted state is now done by passing the state into thestate: ...
property of theinterpret
options argument:-interpret(machine).start(state); +interpret(machine, { state }).start();
The persisted state is obtained from an actor by calling
actor.getPersistedState()
:const actor = interpret(machine).start(); const persistedState = actor.getPersistedState(); // ... const restoredActor = interpret(machine, { state: persistedState }).start();
-
#3889
b394cf188
Thanks @davidkpiano! - Autoforwarding events is no longer supported and theautoForward
property has been removed.Instead of autoforwarding, events should be explicitly sent to actors:
invoke: { id: 'child', src: 'someSrc', - autoForward: true }, // ... on: { // ... + EVENT_TO_FORWARD: { + actions: sendTo('child', (_, event) => event) + } }
-
#3815
66bc88a68
Thanks @davidkpiano! - Theinterpret(...)
function now acceptsinput
in the second argument, which passes input data in the"xstate.init"
event:const greetMachine = createMachine({ context: ({ input }) => ({ greeting: `Hello ${input.name}!` }), entry: (_, event) => { event.type; // 'xstate.init' event.input; // { name: 'David' } } // ... }); const actor = interpret(greetMachine, { // Pass input data to the machine input: { name: 'David' } }).start();
-
#3743
30c561e94
Thanks @davidkpiano! - Invoked actors can now be deeply persisted and restored. When the persisted state of an actor is obtained viaactor.getPersistedState()
, the states of all invoked actors are also persisted, if possible. This state can be restored by passing the persisted state into thestate: ...
property of theinterpret
options argument:-interpret(machine).start(state); +interpret(machine, { state }).start();
-
#3915
9e18af130
Thanks @davidkpiano! - Theactor.onTransition(...)
method has been removed in favor of.subscribe(...)
const actor = interpret(machine) - .onTransition(...) - .start(); +actor.subscribe(...); +actor.start();
-
#3877
1269470bd
Thanks @davidkpiano! - Observing an actor viaactor.subscribe(...)
no longer immediately receives the current snapshot. Instead, the current snapshot can be read fromactor.getSnapshot()
, and observers will receive snapshots only when a transition in the actor occurs.const actor = interpret(machine); actor.start(); // Late subscription; will not receive the current snapshot actor.subscribe((state) => { // Only called when the actor transitions console.log(state); }); // Instead, current snapshot can be read at any time console.log(actor.getSnapshot());
-
#3878
bb9103714
Thanks @davidkpiano! - Actors can no longer be stopped directly by calling. They can only be stopped from its parent internally (which might happen when you useactor.stop()
stop
action or automatically when a machine leaves the invoking state). The root actor can still be stopped since it has no parent. -
#3884
aa80811e5
Thanks @davidkpiano! - Custom action objects and guard objects are now expected to put extra parameters on theparams
property:actions: { type: 'sendMessage', - message: 'hello' + params: { + message: 'hello' + } } guard: { type: 'exists', - prop: 'user' + params: { + prop: 'user' + } }
-
#3924
c4e58c88d
Thanks @davidkpiano! - ThefromReducer(...)
function is now calledfromTransition(...)
. -
#3890
326937415
Thanks @davidkpiano! - Thestate._sessionid
property has been removed. It should be obtained directly from the actor:actor.sessionId
. -
#3756
67d576190
Thanks @Andarist! - All transitions became internal by default. The style of thetarget
pattern (.child
,sibling
,#id
) has now no effect on the transition type.Internal transitions don't reenter their source state when the target lies within it. You can still create external transitions (ones that reenter the source state under the mentioned circumstances) by explicitly setting
external: true
on the given transition.