Skip to content

Commit

Permalink
Fixed an issue with actions of initial transitions being called too m…
Browse files Browse the repository at this point in the history
…any times (#4356)
  • Loading branch information
Andarist authored Oct 16, 2023
1 parent 04cad53 commit 81b6eda
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-needles-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Fixed an issue with actions of initial transitions being called too many times.
7 changes: 2 additions & 5 deletions packages/core/src/stateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,6 @@ function enterStates(
let nextState = currentState;
const statesToEnter = new Set<AnyStateNode>();
const statesForDefaultEntry = new Set<AnyStateNode>();

computeEntrySet(
filteredTransitions,
historyValue,
Expand All @@ -1181,10 +1180,8 @@ function enterStates(
}

if (statesForDefaultEntry.has(stateNodeToEnter)) {
for (const stateNode of statesForDefaultEntry) {
const initialActions = stateNode.initial!.actions;
actions.push(...initialActions);
}
const initialActions = stateNodeToEnter.initial!.actions;
actions.push(...initialActions);
}

nextState = resolveActionsAndContext(
Expand Down
48 changes: 48 additions & 0 deletions packages/core/test/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2122,6 +2122,54 @@ describe('initial actions', () => {

expect(actual).toEqual(['entryC', 'initialBar', 'entryBar']);
});

it('should execute actions of initial transitions only once when taking an explicit transition', () => {
const spy = jest.fn();
const machine = createMachine({
initial: 'a',
states: {
a: {
on: {
NEXT: 'b'
}
},
b: {
initial: {
target: 'b_child',
actions: () => spy('initial in b')
},
states: {
b_child: {
initial: {
target: 'b_granchild',
actions: () => spy('initial in b_child')
},
states: {
b_granchild: {}
}
}
}
}
}
});

const actorRef = createActor(machine).start();

actorRef.send({
type: 'NEXT'
});

expect(spy.mock.calls).toMatchInlineSnapshot(`
[
[
"initial in b",
],
[
"initial in b_child",
],
]
`);
});
});

describe('actions on invalid transition', () => {
Expand Down

0 comments on commit 81b6eda

Please sign in to comment.