Xstate: BUG: array of invoked services overwrites itself in nested states

Created on 14 Feb 2019  路  1Comment  路  Source: davidkpiano/xstate

Bug or feature request?

Bug

Description:

It's not possible to provide an array to the invoke key in any other state than a top-level one, only the last service is kept & found.

(Bug) Expected result:

All services are invoked.

(Bug) Actual result:

Only the last service is invoked, all others write warnings to the console:

No service found for invocation 'machine.one.two.invocation[0]' in machine 'machine'

Where that selector & ID string are different per machine.

(Bug) Potential fix:

https://github.com/davidkpiano/xstate/blob/c7392dc48b11103d716348a6b1230c6507575645/src/StateNode.ts#L287-L290

I'm pretty sure this.machine.options.services should be included in that object spread, to avoid it being overwritten every time the array of services iterates.

Link to reproduction or proof-of-concept:

https://codesandbox.io/s/zr7r6z955l?expanddevtools=1&module=%2Fsrc%2Findex.js

const machine = Machine({
    id: "machine",
    initial: "one",

    states: {
        one: {
            initial: "two",

            states: {
                two: {
                    invoke: [
                        // Never invoked, throws a warning
                        {
                            id: "child",
                            src: () => () => {
                                console.log("first");

                                return () => {};
                            },
                        },
                        // Because when this one was iterated it overwrote
                        // the previous this.machine.options.services object
                        {
                            id: "child2",
                            src: () => () => {
                                console.log("second");

                                return () => {};
                            },
                        },
                    ],
                },
            },
        },
    },
});
bug

Most helpful comment

Same happens when using parallel sub states with single service invocation. Here's a slight variation of the above scenario.

https://codesandbox.io/s/p54nkxy520

const machine = Machine({
  id: "machine",
  initial: "one",

  states: {
    one: {
      initial: "two",
      states: {
        two: {
          type: "parallel",
          states: {
            a: {
              invoke: {
                id: "child",
                src: () => () => {
                  console.log("first");

                  return () => {};
                }
              }
            },
            b: {
              invoke: {
                id: "child2",
                src: () => () => {
                  console.log("second");

                  return () => {};
                }
              }
            }
          }
        }
      }
    }
  }
});

>All comments

Same happens when using parallel sub states with single service invocation. Here's a slight variation of the above scenario.

https://codesandbox.io/s/p54nkxy520

const machine = Machine({
  id: "machine",
  initial: "one",

  states: {
    one: {
      initial: "two",
      states: {
        two: {
          type: "parallel",
          states: {
            a: {
              invoke: {
                id: "child",
                src: () => () => {
                  console.log("first");

                  return () => {};
                }
              }
            },
            b: {
              invoke: {
                id: "child2",
                src: () => () => {
                  console.log("second");

                  return () => {};
                }
              }
            }
          }
        }
      }
    }
  }
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

hnordt picture hnordt  路  3Comments

ifokeev picture ifokeev  路  3Comments

3plusalpha picture 3plusalpha  路  3Comments

bradwoods picture bradwoods  路  3Comments

suku-h picture suku-h  路  3Comments