v4.7.0
- 🐌 If a subscriber/listener subscribes to a service that is already running, it will now receive the current state upon subscription. #814
- 🆙 The new
escalate()
action creator escalates custom error events to a parent machine, which can catch those in theonError
transition:
import { createMachine, actions } from 'xstate';
const { escalate } = actions;
const childMachine = createMachine({
// ...
// This will be sent to the parent machine that invokes this child
entry: escalate({ message: 'This is some error' })
});
const parentMachine = createMachine({
// ...
invoke: {
src: childMachine,
onError: {
actions: (context, event) => {
console.log(event.data);
// {
// type: ...,
// data: {
// message: 'This is some error'
// }
// }
}
}
}
});
- ❓ You can now specify
undefined
as the first argument formachine.transition(...)
, which will default to the initial state:
lightMachine.transition(undefined, 'TIMER').value;
// => 'yellow'
-
🤝 Services (invoked machines) are now fully subscribable and can interop with libraries that implement TC39 Observbles like RxJS. See https://xstate.js.org/docs/recipes/rxjs.html for more info.
-
🆔 When a service is invoked, it has a uniquely generated
sessionId
, which corresponds to_sessionid
in SCXML. This ID is now available directly on the state object to identify which service invocation the state came from:state._sessionid
#523 -
⚙️ The original
config
object passed toMachine(config)
(orcreateMachine(config)
) is now the exact same object reference in the resultingmachine.config
property. -
🎰 The
createMachine()
factory function now exists and is largely the same asMachine()
, except with a couple differences:- The generic type signature is
<TContext, TEvent, TState>
instead of<TContext, TStateSchema, TEvent>
. - There is no third argument for specifying an initial
context
. Use.withContext(...)
on the machine or return a machine with the expectedcontext
in a factory instead.
- The generic type signature is
-
🛑 Event sent to a stopped service will no longer execute any actions, nor have any effect. #735
-
🚸 The invoked actors are now directly available on
state.children
. -
✍️ Plain strings can now be logged in the
log()
action creator:
entry: log('entered here', 'some label')
- 🚄 Transitions are now available on
state.transitions
, which is an array of transition objects that detail exactly which transitions were enabled to transition to this state. This will be ignored in serialization. - ⏩ New action creator:
forwardTo()
https://xstate.js.org/docs/guides/actions.html#forward-to-action - ➕ Assigners now have a third
meta
argument passed in, which contains meta data such as thestate
and the originalaction
- *️⃣ New event type: the wildcard! https://xstate.js.org/docs/guides/transitions.html#wildcard-descriptors
const quietMachine = Machine({
id: 'quiet',
initial: 'idle',
states: {
idle: {
on: {
WHISPER: undefined,
// On any event besides a WHISPER, transition to the 'disturbed' state
'*': 'disturbed'
}
},
disturbed: {}
}
});
quietMachine.transition(quietMachine.initialState, 'WHISPER');
// => State { value: 'idle' }
quietMachine.transition(quietMachine.initialState, 'SOME_EVENT');
// => State { value: 'disturbed' }
- 📲 New action creator:
respond()
https://xstate.js.org/docs/guides/actions.html#respond-action - ✅ New typechecking feature: Typestates https://xstate.js.org/docs/guides/typescript.html#typestates-coming-soon
- 📄 SCXML event metadata is now available on
state._event
and also in action/guard/etc. meta under_event
. https://www.w3.org/TR/scxml/#InternalStructureofEvents