Xstate: [Feature] Support local transitions

Created on 3 Feb 2018  Â·  7Comments  Â·  Source: davidkpiano/xstate

Feature

Description:

A local transition is a transition from a state to its substate which sidesteps _exiting_ the source state, since (because the target is a child state) after the transition, the new configuration will include the source state.

The opposite, an external transition would be a transition to ones children that _exits_ the current state and _enters_ it again.

Potential implementation:

What the API would look like

A transition can already be expressed as plain strings or objects, so I suggest these local transitions be specified in the object form only:

on: {
  EVENT: { target: "foo", type: "local" }
}

The default would probably be an external event, as that's probably backwards compatible, however local events (where possible) do make sense to consider them being local by default.

Perhaps "internal" should be used to be more in line with SCXML? Local stems form Wikipedia and UML.

This is not a breaking change

statecharts.github.io describes the concept: https://statecharts.github.io/glossary/local-transition.html — It includes a workaround for xstate that more or less gives you the same result.

All 7 comments

(to provide some visuals) For a real life example, imagine a word editor with left, right, center, justify buttons:

This can be simplified with internal transitions:

And this could look like this:

Machine({
  key: 'wordEditor',
  initial: 'left',
  states: {
    left: {},
    right: {},
    center: {},
    justify: {}
  },
  on: {
    // internal transitions
    LEFT_CLICK: '.left',
    RIGHT_CLICK: '.right',
    CENTER_CLICK: '.center',
    JUSTIFY_CLICK: '.justify',
  }
});

Prepending with a dot, e.g., '.left', would signify that the state machine would exit the child state, handle the event from the parent state, which internally transitions to its child.

From my understanding (in this example), the parent state 'wordEditor' doesn't exit/enter, but its children do.

Also, re: the above example, LEFT_CLICK: '.left' would be an internal transition (wordEditor never exits/reenters) whereas LEFT_CLICK: 'wordEditor.left' would be an external transition (following the same behavior as a self-transition) which would exit/reenter wordEditor.

In real life, this would be like a RESET button, where you'd want the parent state to exit/reenter.

I think that makes a lot of sense, since this dot prefix is only relevant when transition to child states. It also fits well with e.g. wordEditor.left being a normal, _external_ transition, and wordeditor being a self transition.

Local transitions are in! (see localTransitions.test.ts)

(to provide some visuals) For a real life example, imagine a word editor with left, right, center, justify buttons:

This can be simplified with internal transitions:

And this could look like this:

Machine({
  key: 'wordEditor',
  initial: 'left',
  states: {
    left: {},
    right: {},
    center: {},
    justify: {}
  },
  on: {
    // internal transitions
    LEFT_CLICK: '.left',
    RIGHT_CLICK: '.right',
    CENTER_CLICK: '.center',
    JUSTIFY_CLICK: '.justify',
  }
});

Prepending with a dot, e.g., '.left', would signify that the state machine would exit the child state, handle the event from the parent state, which internally transitions to its child.

From my understanding (in this example), the parent state 'wordEditor' doesn't exit/enter, but its children do.

Need some help about concept clarification here:

In the "word editor" example, transitions from superstate to substates can be treated as a simplication of the transitions in Figure 6.12. Wikipedia refer these transitions as "local transition" rather than "internal transitions", which is fine as long as "internal transition" has anothoer well-defined meaning.

But I found it hard to understand the transitions from substates to superstates. I think "superstates" are somewhat "abstract", which means a state machine can't be in any superstates, in fact, they should be exactly be one of the leaf substates of the superstates.

Does transtions from a substate to its superstate means a internal transition from the substate to the default initial state of that superstate? But that will obviously trigger the exit/enter actions.

a state machine can't be in any superstates, in fact, they should be exactly be one of the leaf substates of the superstates.

  1. When a machine is in a leaf state it is also in every ancestor state containing this leaf
  2. If any ancestor is a parallel state then a machine can be in more than one leaf state (there is no restriction in how many leafs ot can be as you can create any number of parallel states)

Does transtions from a substate to its superstate means a internal transition from the substate to the default initial state of that superstate? But that will obviously trigger the exit/enter actions.

Yes, this description seems to be accurate.

image

Thanks! Now I get it, according to wikipedia.

In the top row, you see the case of the main source containing the main target. The local transition does not cause exit from the source, while the external transition causes exit and reentry to the source. In the bottom row of Figure 8, you see the case of the main target containing the main source. The local transition does not cause entry to the target, whereas the external transition causes exit and reentry to the target.

  1. In the top row, we can interpret the transition as an internal transition as in Figure 6.12, hence "the local transition does not cause exit from the source".
  2. In the bottom row, its actually an internal transition from a state to its parent's default initial state, hence "the local transition does not cause entry to the target".
Was this page helpful?
0 / 5 - 0 ratings

Related issues

3plusalpha picture 3plusalpha  Â·  3Comments

pke picture pke  Â·  3Comments

bradwoods picture bradwoods  Â·  3Comments

suku-h picture suku-h  Â·  3Comments

laurentpierson picture laurentpierson  Â·  3Comments