(Posting here after a suggestion from the forum on Spectrum)
It would be great if xstate could support targetless transitions, where an event can be consumed (perhaps emitting actions) without a change of state. Here's an example machine plus some transitions (in 3.3.2, the final transition displays an error):
const { Machine } = require('xstate');
const machine = Machine({
key: 'test',
initial: 'first',
states: {
first: {
onEntry: 'enter',
onExit: 'exit',
initial: 'one',
states: {
one: {
on: {
NEXT: 'two',
},
},
two: {},
},
on: {
NEXT: [
{
actions: ['ping'],
},
],
},
},
},
});
const log = (ix, state) => {
console.log(`${ix}\n\n${JSON.stringify(state, null, 4)}\n\n`);
};
const state1 = machine.initialState;
log(1, state1);
const state2 = machine.transition(state1, 'NEXT');
log(2, state2);
const state3 = machine.transition(state2, 'NEXT');
log(3, state3);
This feature does appear to be part of SCXML (at least, "targetless transition" is defined and used: I confess to not reading the spec in detail).
I guess it could be useful in some machines to be able to swallow an event even if no actions are emitted, as it would stop the event bubbling to an ancestor.
Using a transition config object, minus the target property, would seem a reasonable way to define a targetless transition. Breaking change? Potentially in minor edge cases, I guess.
Done. There are two ways to define a targetless transition:
{
on: {
EVENT: {
// empty target
'': { actions: ['doSomething'] }
}
}
}
// or within a conditional array:
{
on: {
// no target
EVENT: [{ actions: ['doSomething'] }]
}
}
Most helpful comment
Done. There are two ways to define a targetless transition: