Use a final state instead of a global id target
Say you have the following state machine:
When receiving a click
event, the state machine goes from the A
state to the B
state.
Now, say you need to make A
a compound state with child states and move the listener for the click
to a sub-state. How do you target the B
state now?
We can’t use target: "B"
because it only works for sibling states. The A
and B
states can target the other one that way, and firstStep
and secondStep
too. But secondStep
and B
are not at the same depth in the state machine and can’t use this target.
This doesn’t work:
The first option is to use a global id to target the B
state:
Using a global id works—continue reading for my recommended solution. For your information, it’s also possible to use the implicit id XState attributes to each state, formed with the id of the state machine and the path to the state:
Global ids share the advantages and disadvantages of global variables: they seem straightforward to solve a problem but make the code harder to follow.
Though it might be okay to use a global id as a target sparingly, I often prefer to rely on final states.
With final states, we can mark a compound state as done. We can then leverage the onDone
special event listener to transition to another state:
To me, the benefits of using final states are:
- It clarifies that the state represents some process and has an end-state.
- Compound states act as a layer of abstraction; their child states don’t have to know what happens outside.
- Many transitions can target the final state and make it possible to centralize some end-logic.
The User Activity example uses a final state for these reasons:
Get news from XState by Example
Sign up for the newsletter to be notified when more machines or an interactive tutorial are released. I respect your privacy and will only send emails once in a while.