Skip to content

Instantly share code, notes, and snippets.

@kbingman
Created July 7, 2021 16:15
Show Gist options
  • Save kbingman/beee5dbc29230c6253fcf34e7f17e81e to your computer and use it in GitHub Desktop.
Save kbingman/beee5dbc29230c6253fcf34e7f17e81e to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const fetchMachine = Machine(
{
id: 'fetch-machine',
initial: 'idle',
context: {
q: '',
offset: 0,
results: [],
filters: {},
error: '',
query: '', // the search term in the box
},
states: {
idle: {
on: {
FETCH_RESULTS: {
target: 'pending',
actions: 'updateParams',
cond: 'checkQuery',
},
},
},
pending: {
// injected when the state machine is invoked
// redirects the application to the correct URL
entry: ['redirectToSearch'],
on: {
LOAD_RESULTS: {
target: 'success',
actions: 'loadData',
},
ERROR: {
target: 'failure',
actions: 'assignError',
},
},
},
success: {
on: {
FETCH_RESULTS: {
target: 'pending',
actions: 'updateParams',
cond: 'checkQuery',
},
TOGGLE_FILTER: {
target: 'pending',
actions: 'toggleFilter',
},
CLEAR_FILTER: {
target: 'pending',
actions: 'clearFilter',
},
},
},
retry: {
invoke: {
id: 'retry-fetch',
// injected when the state machine is invoked
// retries the API request
src: 'invokeRetryFetch',
onDone: {
target: 'success',
actions: 'loadData',
},
onError: {
target: 'failure',
actions: 'assignError',
},
},
},
failure: {
on: {
FETCH_RESULTS: {
target: 'retry',
actions: 'updateParams',
},
},
},
},
on: {
LOAD_RESULTS: {
target: 'success',
actions: 'loadData',
},
ERROR: {
target: 'failure',
actions: 'assignError',
},
RESET: {
target: 'idle',
actions: 'resetData',
},
SET_QUERY: {
target: 'idle',
actions: 'setQuery',
},
},
},
{
actions: {
assignError: assign((ctx, evt) => ({
...ctx,
error: evt.data?.message,
query: evt.data?.query || ctx.query,
})),
setQuery: assign((_, evt) => ({
query: evt.query || '',
})),
updateParams: assign((ctx) => ({
q: ctx.query,
offset: 0,
})),
loadData: assign((ctx, evt) => {
return {
q: evt.data.q || '',
query: evt.data.q || '',
offset: evt.data.offset || 0,
results: evt.data.results || [],
filters: addMissingFilters(
ctx.filters,
evt.data.filters,
evt.data.selected
),
error: null,
};
}),
resetData: assign((_ctx) => ({
q: '',
results: [],
filters: {},
error: '',
})),
toggleFilter: assign((ctx, evt) => {
const selected = ctx.filters[evt.key]?.selected || new Set();
if (selected.has(evt.id)) {
selected.delete(evt.id);
} else {
selected.add(evt.id);
}
return {
offset: 0,
filters: {
...ctx.filters,
[evt.key]: {
...ctx.filters[evt.key],
selected,
},
},
};
}),
clearFilter: assign((ctx, evt) => ({
filters: {
...ctx.filters,
[evt.key]: {
...ctx.filters[evt.key],
selected: new Set(),
},
},
})),
},
guards: {
checkQuery: (ctx) => ctx.q !== ctx.query,
checkFilterSelection: (ctx, evt) =>
ctx.filters[evt.key]?.selected?.size > 0,
},
}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment