Skip to content

Instantly share code, notes, and snippets.

@cevr
Created December 16, 2019 23:41
Show Gist options
  • Save cevr/f2f83bbd2ba3bd2ba1d9b9153abcaaf3 to your computer and use it in GitHub Desktop.
Save cevr/f2f83bbd2ba3bd2ba1d9b9153abcaaf3 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 FormMachineTypes = {
FOCUS : 'FOCUS',
BLUR : 'BLUR',
CHANGE : 'CHANGE',
SUBMIT : 'SUBMIT',
}
const fetchMachine = Machine( {
id: 'form',
initial: 'idle',
context: {
values: {},
errors: {},
refs: {},
},
states: {
idle: {
initial: 'noError',
on: {
[FormMachineTypes.CHANGE]: [
{
target: 'idle.error',
cond: 'hasErrors',
actions: ['resetError', 'setValue'],
},
{
target: 'idle.noError',
actions: ['resetError', 'setValue'],
},
],
[FormMachineTypes.BLUR]: 'validatingField',
[FormMachineTypes.SUBMIT]: '#form.validating',
},
states: {
noError: {},
error: {},
submitError: {},
},
},
validatingField: {
invoke: {
src: 'validateField',
onDone: 'idle.noError',
onError: {
target: 'idle.error',
actions: ['setErrors', 'focusInput'],
},
},
},
validating: {
entry: ['resetErrors'],
invoke: {
src: 'validate',
onDone: 'submitting',
onError: {
target: 'idle.error',
actions: ['setErrors', 'focusInput'],
},
},
},
submitting: {
invoke: {
src: 'handleSubmit',
onDone: {
actions: 'onSubmit',
target: 'submitted',
},
onError: {
target: 'idle.submitError',
actions: 'setSubmitError',
},
},
},
submitted: {
type: 'final',
},
},
},
{
guards: {
hasErrors: context => Object.values(context.errors).some(Boolean),
},
actions: {
setValue: assign((context, event) => ({
values: {
...context.values,
[event.name]: event.value,
},
})),
setErrors: assign({
errors: (context, event) => ({
...context.errors,
...event.data,
}),
}),
focusInput: (context, event) => {
// this will look at the first input and focus it for some pleasant UX
const first = Object.keys(event.data)[0];
context.refs[first].current.focus()
},
// this looks at the fetch error message
setSubmitError: assign({
errors: (context, event) => ({
...context.errors,
submit: event.data.message,
}),
}),
// when validating field, ensure no stale error passes through
resetError: assign({
errors: (context, event) => {
if (!context.errors[event.name]) return context.errors;
return {
...context.errors,
[event.name]: undefined,
};
},
}),
// when validating, ensure no stale errors pass through
resetErrors: assign({
errors: {},
}),
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment