0

I want to execute an action in every state's entry. How can I do that?

It can be done like this:

const promiseMachine = createMachine({
  id: "promise",
  initial: "pending",
  states: {
    pending: {
      entry: ["myAction"]
    },
    resolved: {
      entry: ["myAction"]
    },
    rejected: {
      entry: ["myAction"]
    }
  }
});

However, I have 10+ states, it becomes repetitive to write the same code over and over again.

user9408899
  • 4,202
  • 3
  • 19
  • 32
  • Are you able to provide some more context of your actual use case? – chautelly Apr 24 '23 at 23:18
  • I was wondering the same as @chautelly . The solution could be simple if you just want to log something for example. Could be a case of https://xyproblem.info/ – Tobi Obeck Apr 25 '23 at 09:35

2 Answers2

1

For every received event you can check on the state instance (docs, old docs) whether a state change did occur. This comes close to performing an action during entry. But I would advise against using such a pattern. It kinda defeats the purpose of using a state machine which is used to precisely define what should happen in each particular state transition.

Example in Svelte:

const { state, send, service } = useMachine(toggleMachine); // for react const [state, send, service]

let oldState = $state.value

service.onTransition((state, event) => {
  if(state.changed && state.value !== oldState){
    // perform some side-effect
    console.log(state.value, state.context)
  }
  oldState = state. Value
});

Alternatively, you can define the machine as type: 'parallel' and have one state with the actual state machine implementation and another with a wildcard transition (docs) for capturing all events that are received. This comes also somewhat close, but triggers for all events! Even events that don't lead to a transition in the actual state machine implementation.

'capturing-all-events': {
  on: {
    "*": {
      internal: true,
      actions: "myAction",
    },
  },
},

Keep in mind there are also utility functions for actions like logging: https://stately.ai/docs/xstate/actions/built-in-actions#log-action

Tobi Obeck
  • 1,918
  • 1
  • 19
  • 31
0

Iterate config before creating machine.

For example

const config = {
  id: "promise",
  initial: "pending",
  states: {
    pending: {
      entry: []
    },
    resolved: {
      entry: []
    },
    rejected: {
      entry: []
    }
  }
}

Object.values(config.states).forEach(it=>{
  it.entry.push('myAction')
})

createMachine(config);
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78