Reputation: 2566
I'm using xstate in my React Native app to manage a rather complex flow. I would like to systematically log analytics events on each state transition and event happening in the state machine. So far, I haven't figured how to do that without manually calling a logEvent
action from every event. For example on a much smaller machine than the one I built:
const machine = createMachine({
id: 'machine',
initial: 'idle',
context: {},
states: {
idle: {
on: {
NEXT: {
target: 'green',
actions: ['logEvent'] // <-------- here
}
}
},
green: {
on: {
NEXT: {
target: 'green',
actions: ['logEvent'] // <-------- here
},
BACK: {
target: 'idle',
actions: ['logEvent'] // <-------- here
},
}
},
red: {
on: {
NEXT: {
target: 'idle',
actions: ['logEvent'] // <-------- here
},
BACK: {
target: 'green',
actions: ['logEvent'] // <-------- here
},
}
}
}
})
So much repetition :(
Another way I read about was using interpret
and adding a onTransition
listener (https://xstate.js.org/docs/guides/interpretation.html#transitions). However this requires to also manually send event for the onTransition listener to fire, so it's not a solution imo.
I also found @xstate/analytics, but there are no docs and README says we shouldn't use it ^^
Is there a way to call an action on each transition without repeating myself so much?
Upvotes: 2
Views: 836
Reputation: 637
You could try having it as an entry action on for every state.
const machine = createMachine({
id: 'machine',
initial: 'idle',
context: {},
states: {
idle: {
entry: ['logEvent'],
on: {
NEXT: {
target: 'green',
}
}
},
green: {
entry: ['logEvent'],
on: {
NEXT: {
target: 'green',
},
BACK: {
target: 'idle',
},
}
},
red: {
entry: ['logEvent'],
on: {
NEXT: {
target: 'idle',
},
BACK: {
target: 'green',
},
}
}
}
})
Upvotes: 2