xstate: onTransition does not fire after every transition
Description
onTransition does not fire with `always’
Expected Result A few choices:
- document that
onTransitiononly fires when the “machine ‘settles’” & keep behavior as-is onTransitionalways fires, including withalways- configure if
onTransitionfires withalways, or makeonTransitionAlways
Reproduction https://tombyrer.github.io/cat-christmas/cat-christmas
Additional context reference issue
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 4
- Comments: 16 (13 by maintainers)
I firmly believe that the issue presented here is sound. From my PoV, it’s not about functional shortcomings (I don’t have a use case that is not satisfied by the current APIs) but rather about semantic discrepancies.
If we call something a transition and we later provide the onTransition callback I would fully expect for it to be fired after every transition. Otherwise, we just end up confusing new learners because it’s not obvious that this actually behaves differently. And as shown by the issue here - it’s not a theoretical learning problem because @tomByrer (and myself in the past as well) has assumed a different behavior than the one that is currently implemented. This becomes even more of a problem because we’ve recommended using the
onTransitionto handle some logic whenever something happens (like getting a particular value in the context) in multiple issues - and currently some occurrences of the desired situation might be “skipped”, which is not obvious.I understand that this mainly~ comes from the fact that this is called after
machine.transition()which actually resolves all microsteps but maybe then this method should not be calledtransitioneither? This is a low-level API and as such, I actually wouldn’t mind a different resolution either - we could rethink if this actually should resolve all microsteps. Maybe it should be up to the interpreter to handle the resolution of the microsteps? From the final consumer’s PoV this actually wouldn’t matter much (unless they depend on the raw Machine API - but those users are already “advanced” so I don’t mind requiring more of them). This could actually simplify various stuff like SCXML compatibility with action order & error handling, semantic correctness, and even visualization (I believe that representing microsteps on the visualization is also important for the reasoning process, at times it might not be obvious why we have jumped directly from A to B without seeing the whole “path”)Yet a new learner here +1 come from XState Learning Curve
Looking forward to using the
onMicrostepin v5!And just my 2 cents: I feel it’s better to make a breaking change in v5: (from a new learner perspective)
onTransitionin v4 toonBatchTransitionin v5onTransitionin v5 should be the newonMicrostepThis will be coming to v5:
Writing these docs this weekend.
See the latest merged PR for the inspect API to see usage.
While I do lean more towards Andarist’s perspective of “confusing new learners” (like me 😃 ). I want to provide counter perspective; skipping
always {}does provide a neat way to separate out each ‘thing to do’ into individual steps, rather than having to combine an action step & timer step like I did withplay{}stateIn my demo above, I assumed that all
always{}were triggered inonTransition, where I was going to update the DOM.I don’t have a strong use-case for
onTransitionAlwaysright now; just brainstorming. There are workarounds, I don’t need to have `it…Better docs of how the current system works would help if you don’t want to add ; I was not aware of ‘microsteps’ in XState until yesterday, despite referring to the docs & Discussions 100 times.