statelyai / xstate

Actor-based state management & orchestration for complex app logic.
https://stately.ai/docs
MIT License
26.98k stars 1.24k forks source link

Bug: When child state transitioned to final state, did not trigger onDone event and transition to next state #4858

Open lvchenyang opened 5 months ago

lvchenyang commented 5 months ago

XState version

XState version 5

Description

The state machine define:

const machine1 = createMachine({
  id: "machine1",
  initial: "idle",
  states: {
    idle: {
      on: {
        START: {
          target: "finished",
        },
      },
    },
    finished: {
      type: "final",
    },
  },
});

const machine2 = createMachine({
  id: "machine2",
  initial: "idle",
  states: {
    idle: {
      on: {
        START: {
          target: "finished",
        },
      },
    },
    finished: {
      type: "final",
    },
  },
});

const parentMachine = setup({
  actors: {
    machine1,
    machine2
  }
}).createMachine({
  id: "parent",
  initial: "step1",
  states: {
    step1: {
      invoke: {
        src: machine1,
        onDone: {
          target: "step2",
        },
      },
    },
    step2: {
      invoke: {
        src: machine2,
      },
      type: "final",
    },
  },
});

Child Component

interface ChildComponentProps {
  machine: AnyStateMachine;
  children: ReactNode;
}
const ChildComponent = ({ machine, children }: ChildComponentProps) => {
  const [state, send] = useActor(machine);
  console.log("Child State:", state.value);
  const handleClick = () => {
    send({ type: "START" });
  };
  return <button onClick={handleClick}>{children}</button>;
};

ParentComponent

function App() {
  const [state] = useActor(parentMachine);

  console.log("Parent State:", state.value);
  return (
    <>
      {state.value === "step1" && (
        <ChildComponent machine={machine1}>Child Machine 1</ChildComponent>
      )}
      {state.value === "step2" && (
        <ChildComponent machine={machine2}>Child Machine 2</ChildComponent>
      )}
    </>
  );
}

The question is when Child Machine 1 button clicked, child state transitioned to final state, but parent state machine has no state transitions.

Expected result

Child Machine 1 button clicked, show Child machine 2 button.

Actual result

Always show Child Machine 1 button.

Reproduction

https://codesandbox.io/p/sandbox/child-state-example-2d5q5n

Additional context

No response