Major Changes
-
c3f7a9d: Actor logic now returns effects from both regular and initial transitions.
Hand-written actor logic should return
[snapshot, effects]fromtransition(...)and provideinitialTransition(...)for creating the initial[snapshot, effects]tuple.getInitialSnapshot(...)remains available for snapshot-only reads.const logic = { transition: (snapshot, event) => [snapshot, []], initialTransition: (input, _scope) => [ { status: 'active', output: undefined, error: undefined, input }, [] ], getInitialSnapshot: (scope, input) => logic.initialTransition(input, scope)[0] };
transition(...)andinitialTransition(...)continue to return[snapshot, actions]for machine logic.fromStore(...)effects now run after the actor snapshot is committed, so effect callbacks read the updated snapshot fromenqueue.getSnapshot(). -
309b106: Add
schemas.childrenfor explicitly typing child actor refs by child ID. Declared child refs typechildren.someId, child snapshots, and invoke configs soinvoke: { id: 'someId', src }must match the declared child actor contract. -
fa2bbf0: Built-in executable effects returned from
transition(...)andinitialTransition(...)are now easier to inspect declaratively.Use
isBuiltInExecutableAction(effect)to narrow an executable effect to XState's built-in effect union, then switch oneffect.typeto access stable, named metadata fields:const [snapshot, effects] = initialTransition(machine); for (const effect of effects) { if (!isBuiltInExecutableAction(effect)) { continue; } switch (effect.type) { case '@xstate.start': effect.id; effect.logic; effect.src; effect.input; break; case '@xstate.sendTo': effect.target; effect.event; effect.delay; break; case '@xstate.raise': effect.event; effect.delay; break; } }
The built-in stop effect is now exposed as
@xstate.stop, matching@xstate.start.