xstate: Assign action in entry get a wrong state

Description Action in entry will get different state for assign action and non-assign action;

const machine = createMachine<ToggleContext, ToggleEvent>(
  {
    id: "machine",
    initial: "inactive",
    context: {
      count: 0
    },
    states: {
      inactive: {
        on: { TOGGLE: "active" },
        entry: ["assignEntry", "nonAssignEntry"]
      },
      active: {
        on: { TOGGLE: "inactive" },
        entry: ["assignEntry", "nonAssignEntry"]
      }
    }
  },
  {
    actions: {
      assignEntry: assign({
        count: (context, event, { state }) => {
          console.log("assign", state);
          return ++context.count;
        }
      }),
      nonAssignEntry: (context, event, { state }) => {
        console.log("non assign", state);
      }
    }
  }
);

Expected Result They should have same state value, I think the state should be the target state, not previous state;

Actual Result They have different state value: image

Reproduction

Additional context xstate version: 4.22.0

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I think that this one was largely addressed in v5. For starters, we definitely have access to the same data in different action types since we no longer prioritize any of them and all of them are just executed “in order”. The lightNode + entry actions solve @Sczlog’s issue (see the answer to Q2 here). The same mitigates @pke’s problem.

@mattpocock Thanks for the reply. I am not sure about the root cause, but I found In resolveActions function it will process actions first and group them by assign action and other action first, then it will updateContext by assign action first. No matter the assign action is assigned in entry or actions. I think we may need split assign action by entry action and normal action and only do normal assign action in the start of resolveActions? IMO the order should be like this one: normal assign action -> normal other action -> entry assgin action -> entry other action?

You can now add .preserveActionOrder: true in the root machine config to resolve this.