xstate
xstate copied to clipboard
Bug: [V5] Manually Stopping & then Restarting a Machine doesn't trigger it's entry action
XState version
XState version 5
Description
In V4, I manually started and stopped the machine based on certain conditions, which worked correctly (see the provided CodeSandbox link below).
Problem: In V5, while the machine starts correctly for the first time, it fails to trigger the entry action when manually stopped and started again. The entry action in the initial state does not execute on the second attempt to start the machine.
Steps to Reproduce: (check output in console)
- Start the machine manually.
- Stop the machine manually.
- Start the machine manually again.
V4 Example: https://codesandbox.io/p/sandbox/xstate-v4-start-stop-l2xrs6 V5 Example: https://codesandbox.io/p/sandbox/xstate-v5-start-stop-t5xld6
Expected result
The machine should reset on stop() & The entry action in the initial state should trigger each time the machine is started.
Actual result
The entry action does not trigger on the second start.
Reproduction
https://codesandbox.io/p/sandbox/xstate-v5-start-stop-t5xld6
Additional context
No response
createMachine({
initial: "a",
states: {
a: {
on: {
FOO: "b"
}
},
b: {
entry: ({ event }) => {
// event is gone after transition takes place
// we can't call entry actions again on anothr start
// what event they should be called with?
}
}
},
})
@Andarist In my example I am running the event on entering the initial state itself, this works fine with v4, Is there a change between v4 & v5 in how machines handle the entry event? I couldn't find anything in the Documentation about this.
This is what I was doing with v4, should we change the approach while upgrading to v5?
createMachine({
initial: "a",
states: {
a: {
entry: 'doSomething'
}
},
})
A restarted machine like this doesn't completely forget its previous snapshot. When u start again u don't start completely from scratch. If you want to start from scratch then it would be best to create a new instance of this actor.
Ok, so this is different from how interpret did it, it was also mentioned in the docs for it.
https://xstate.js.org/docs/guides/interpretation.html#starting-and-stopping
Thanks, I will try to find a different approach but do you think this might be something that can be a possibility in the future as by stopping a machine you would expect it to destroy itself & then restart from scratch like interpret did.
Ok, so this is different from how
interpretdid it, it was also mentioned in the docs for it. https://xstate.js.org/docs/guides/interpretation.html#starting-and-stoppingThanks, I will try to find a different approach but do you think this might be something that can be a possibility in the future as by stopping a machine you would expect it to destroy itself & then restart from scratch like interpret did.
This would require persisting which effects (actions, invocations) were executed. This may be possible with the future "transition API" #4954
@Andarist maybe this is already explained somewhere, but is there a reason why the .getSnapshot().status after restarting the actor doesn't go back to active? If i try to log the .status after restarting is always stopped.
@andrecrimb currently actors are not exactly suited for reuse, so you shouldn't do smth like actorRef.start().stop().start(). If you need to rehydrate an actor I recommend this:
const snapshot = actorRef.getPersistedSnapshot()
actorRef.stop()
const newActorRef = createActor(machine, { snapshot })