const paymentService = (context, event) => new Promise((resolve, reject) => { // TODO: change this, it's MOCK setTimeout(() => { if (context.plan === 'annual') { return reject('something went wrong'); } return resolve(); }, 2000); }); const subscribeToCoachMachine = Machine({ id: 'subscribeToCoach', context: { plan: 'free', error: undefined, }, initial: 'planSelection', states: { planSelection: { on: { SUBSCRIBE: [ // only go to payment if the plan is not a free one { target: 'enterPaymentInfo', cond: 'notFreePlan' }, { target: 'subscribed', cond: 'isFreePlan' }, ], SELECT: { actions: 'selectPlan', }, }, }, enterPaymentInfo: { on: { PAYMENT: { target: 'paymentProcess', }, }, }, paymentProcess: { invoke: { id: 'paymentService', src: paymentService, onDone: { target: 'subscribed', actions: [], }, onError: { target: 'enterPaymentInfo', actions: assign({ error: (context, event) => event.data }), }, }, }, subscribed: {}, }, }, { actions: { selectPlan: assign({ plan: (_, event) => event.plan, }), }, guards: { notFreePlan: (context) => { return context.plan !== 'free'; }, isFreePlan: (context) => { return context.plan === 'free'; }, }, });