statelyai / xstate

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

A way of extending actionTypes in the interpreter #180

Closed carloslfu closed 5 years ago

carloslfu commented 5 years ago

Bug or feature request?

Feature request

Description:

A way of extending actionTypes in the interpreter is needed. Is very common to use custom actions in statecharts, I want to take advantage of the new type features and add new action types as well as not to display a warn when I use it.

(Feature) Potential implementation:

Maybe to have an actions option in the InterpreterOptions.

davidkpiano commented 5 years ago

A way of extending actionTypes

Can you expand on this? What are you looking to achieve? (Code samples would be appreciated)

carloslfu commented 5 years ago

For instance, on the Flickr example using the interpreter:

import { Machine } from 'xstate'
import { interpret } from 'xstate/lib/interpreter'

const m = Machine({
  initial: 'start',
  states: {
    start: {
      on: {
        SEARCH: 'loading'
      }
    },
    loading: {
      onEntry: ['search'],
      on: {
        SEARCH_SUCCESS: {
          target: 'gallery',
          actions: ['updateItems']
        },
        SEARCH_FAILURE: 'error',
        CANCEL_SEARCH: 'gallery'
      }
    },
    error: {
      on: {
        SEARCH: 'loading'
      }
    },
    gallery: {
      on: {
        SEARCH: 'loading',
        SELECT_PHOTO: 'photo'
      }
    },
    photo: {
      onEntry: ['setPhoto'],
      on: {
        EXIT_PHOTO: 'gallery'
      }
    }
  }
});

const i = interpret(m)

// This might be
/*
const i = interpret(m, {
  actions: {
    search: () => {},
    updateItems: () => {},
    setPhoto: () => {},
  }
})
*/

i.onTransition(x => console.log(x))

i.init()

i.send('SEARCH')
i.send('SEARCH_SUCCESS')
i.send('SELECT_PHOTO')
i.send('EXIT_PHOTO')

// notice that here you got multiple logs like: "No implementation found for action type 'search'"

Link to the working code: https://stackblitz.com/edit/xstate-interpreter-flickr-example?file=index.js

davidkpiano commented 5 years ago

Ah yeah, I previously discussed on Gitter the possibility of adding something like:

const predefinedMachine = Machine({ ... }, ...);

const overrideMachine = predefinedMachine.withConfig({
  actions: { ... },
  guards: { ... }
});

The overrideMachine would have the same configuration as the predefinedMachine, but the actions/guards would override the previously defined ones. Great for testing, etc.

Does that seem like what you'd want? Then the interpreter becomes:

const i = interpret(m.withConfig(...));

// ...
carloslfu commented 5 years ago

Yes, that's it. Thanks.

davidkpiano commented 5 years ago

This is added in master as machine.withConfig({ actions: {}, guards: {} }) (see b2354a4). Will be released on xstate@next soon.

davidkpiano commented 5 years ago

Closing as it is on master and will be released in 4.0.