samzmann
samzmann

Reputation: 2566

How to track analytics events with xstate

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

Answers (1)

cdruc
cdruc

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

Related Questions