Eventless transition inside compound state triggers infinite loop #1592
-
I'd like to ask whether the following is the intended behavior, or rather a bug: My goal: Correct sub-state of a compound state should be selected when the compound state is entered. The target sub-state should be selected by checking some context value. xstate version: 4.13.0 Example: https://codesandbox.io/s/quirky-shamir-ghzwn Expected behavior:
Actual behavior: Reading the docs gave me an impression that the transient transition should be evaluated only once, upon entering the Compound state. Since the transient transition is internal, I wasn't expecting the Compound state to be re-entered and thus triggering the same transient transition again. Am I misinterpreting the docs or is this a bug? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
As long as you're still in a compound state that has an
That For your example, the const machine = Machine({
id: "root",
initial: "Initial",
context: {
mode: 1
},
states: {
Initial: {
on: {
START: "Compound"
}
},
Compound: {
initial: "Default",
states: {
Default: {
always: [
{
cond: (ctx) => ctx.mode === 1,
target: "Mode1"
},
{
cond: (ctx) => ctx.mode === 2,
target: "Mode2"
}
]
},
Mode1: {},
Mode2: {}
}
}
}
}); |
Beta Was this translation helpful? Give feedback.
-
I did a bit of exploring and experimenting to learn how eventless transitions with actions work in detail. Here is what I found. Perhaps someone will find it useful. I will distill key takeaways / recommendations into a documentation update. Codesandbox demonstrating my analysis is here. Disclaimer: That code contains anti-patterns which have been added for exploration purposes (e.g. impure and mutating guard functions; manipulating a variable outside of the state machine context). Don't do this for real. MechanismPhase 1: Guard evaluation loopEventless transitions on a state node are evaluated in a loop. When state node is entered, the algorithm iterates over its eventless transitions and executes their guards before anything else. What happens next depends on what kind of transition is (or isn't) validated:
Note, that in this phase only Phase 2: Executing actions
Phase 3: Waiting for another microtaskWhen the machine receives an event (both internal or external), eventless transitions of the current node will be re-evaluated again (go to Phase 1). Not just any event but only a known event for which there is a transition declared, either in the current node, or its ancestors. Forbidden transitions will trigger Phase 1 as well. Unknown or unhandled events will not. Takeaways
|
Beta Was this translation helpful? Give feedback.
-
PR for updating docs: #1619 This took a while, but I wanted to make sure I did not misrepresent the behavior and kept the docs reasonably concise at the same time. |
Beta Was this translation helpful? Give feedback.
As long as you're still in a compound state that has an
always
transition, that transition will always be checked, regardless of internal or external transitions, I'm pretty sure. Will have to double-check with the SCXML spec on this, but this is the behavior that makes sense. In the SCXML algorithm: