// Available variables: // - Machine // - interpret // - assign // - send // - sendParent // - spawn // - raise // - actions // - XState (all XState exports) const statusEquals = status => context => context?.error?.response?.status === status; const fetchMachine = Machine({ id: 'fetch', initial: 'idle', context: { retries: 0, data: null, error: null, isValidating: false, }, states: { idle: { on: { REQUEST: 'loading' }, }, loading: { invoke: { src: 'load_user', onDone: { target: 'fulfilled', actions: assign({ data: (_, event) => event.data, }), }, onError: { target: 'rejected', actions: assign({ error: (_, event) => event.error, }) } } }, fulfilled: { type: 'final', entry: 'onComplete', on: { RELOAD: 'loading', } }, rejected: { meta: 'Handles API rejections', initial: 'unknown', states: { unknown: { on: { '': [ { target: 'bad request', cond: '400' }, { target: 'unauthorized', cond: '401' }, { target: 'forbidden', cond: '403' } ] } }, 'bad request': { type: 'final', }, 'unauthorized': { type: 'final', }, 'forbidden': { type: 'final', } }, on: { RETRY: 'loading', actions: assign({ retries: (context, event) => { context.retries + 1; } }) } }, } }, { guards: { 400: statusEquals(400), 401: statusEquals(401), 403: statusEquals(403), } });