Xstate: Chosen actions are not applied if it's pure or assign

Created on 22 Apr 2020  路  6Comments  路  Source: davidkpiano/xstate

Description
I'm trying to use the new choose action creator but the chosen actions don't get applied if they are pure or assign.

Only log and send work with me.

Expected Result
The child assign action of the choose to be invoked

Actual Result
The child assign action of the choose didn't get invoked.

Reproduction

Additional context
XState Version: 4.9.1

bug

Most helpful comment

All 6 comments

Given your current code, you shouldn't be using choose(...) at all. What is your use-case for using choose(...)?

Given your current code, you shouldn't be using choose(...) at all. What is your use-case for using choose(...)?

@davidkpiano Thanks for the awesome library.

The code is just a simple example of using the choose(...). in the real world example, I am trying to trigger a different set of actions based on the state of a parallel machine.

But however, even if semantically my use-case doesn't make sense. Based on the docs I think my snippet of code should work differently. Am I right?

@saadshahd yes, it should work - I've located the problem, gonna prepare a PR with the fix soon.

@Andarist Thanks, you are awesome.

@davidkpiano below is a chunk of my real-world use case, I would really appreciate if you looked and suggested some refactoring.

const machine = Machine({
  id: 'collection-room',
  type: 'parallel',
  context: {
    loopInterval: null,
    video: {
      url: '',
      timestamp: 0
    }
  },

  on: {
    SET_VIDEO_TIME_WITH_MODE: {
      actions: ['setVideoTimestampWithMode']
    },
  },

  states: {
    videoMode: {
      id: 'videoMode',
      initial: 'manual',

      states: {
        manual: {
          on: {
            ENTER_LOOP: 'loop'
          }
        },

        loop: {
          exit: 'clearLoopInterval',
          on: {
            ENTER_MANUAL: 'manual'
          }
        }
      }
    },

    activating: {
      id: 'activating',
      initial: 'empty',

      on: {
        CHANGE: [
          { target: 'activating.empty', cond: 'isActiveBaseEmpty' },
          { target: 'activating.start', cond: 'isActiveBaseStart' },
          { target: 'activating.end', cond: 'isActiveBaseEnd' },
          { target: 'activating.full' }
        ]
      },

      entry: [
        ...
        'setLoopIntervalFromActiveWithMode'
      ],

      states: {
        empty: {},
        full: {
          entry: [...]
        },
        start: {
          entry: [...]
        },
        end: {
          entry: [...]
        }
      }
    }
  }
}, {
  actions: {
    setVideoTimestampWithMode: choose([
      {
        cond: 'isManual',
        actions: ['setVideoTimestamp', 'checkActive', 'redirect']
      },
      {
        cond: 'isLoop',
        actions: ['setVideoTimestamp']
      }
    ]),

    setLoopIntervalFromActiveWithMode: choose([
      {
        cond: 'isManual',
        actions: ['clearLoopInterval']
      },
      {
        cond: 'isLoop',
        actions: ['setLoopIntervalFromActive']
      }
    ])
  }
});

I see now that I could easily get rid of setVideoTimestampWithMode by declaring the SET_VIDEO_TIME_WITH_MODE event on the video mode StateNodes instead of the rool level.

But I still can't figure out what could I do better to get rid of setLoopIntervalFromActiveWithMode.

Thanks in advance.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

drmikecrowe picture drmikecrowe  路  3Comments

greggman picture greggman  路  3Comments

mattiamanzati picture mattiamanzati  路  3Comments

hnordt picture hnordt  路  3Comments

kurtmilam picture kurtmilam  路  3Comments