I was exploring the XState world and tried to recreate the machine @davidkpiano mentioned in this talk
And faced an issue with doing the transitions right. When I send a message to parent machine, it resets all the child machines.
For example: I expect the machine to be in dirty and focused state after I fire the CHANGE and FOCUS event one after another. But after sending FOCUS message the pristine state resets back to pristine.
I found this issue, but multiple transitions do the same thing (as it actually described in the issue itself)
Also, I don't want to store all the information about pristine, focused and touched state into the context, because it will not be as safe as doing it with state machines.
The code below is copy-pastable into https://xstate.js.org/viz/
const createPristineMachineConfig = (inputName) => {
return {
id: `${inputName}.pristine`,
initial: 'pristine',
states: {
pristine: {
on: {
[`${inputName}.CHANGE`]: 'dirty',
},
},
dirty: {
type: 'final',
},
},
};
};
const createTouchedConfig = (inputName) => {
return {
id: `${inputName}.touched`,
initial: 'untouched',
states: {
untouched: {
on: {
[`${inputName}.TOUCH`]: 'touched',
},
},
touched: {
type: 'final',
},
},
};
};
const createFocusedMachineConfig = (inputName) => {
return {
id: `${inputName}.focused`,
initial: 'blurred',
states: {
blurred: {
on: {
[`${inputName}.FOCUS`]: 'focused',
},
},
focused: {
on: {
[`${inputName}.BLUR`]: 'blurred',
},
},
},
};
};
const createInputMachineConfig = (inputName) => ({
id: inputName,
type: 'parallel',
context: {
value: '',
},
on: {
FOCUS: {
actions: send(`${inputName}.FOCUS`),
internal: true,
},
BLUR: {
actions: [send(`${inputName}.TOUCH`), send(`${inputName}.BLUR`)],
internal: true,
},
CHANGE: {
actions: [assign((ctx, event) => ({ ...ctx, value: event.payload.value })), send(`${inputName}.CHANGE`)],
internal: true,
},
},
states: {
pristine: createPristineMachineConfig(inputName),
touched: createTouchedConfig(inputName),
focused: createFocusedMachineConfig(inputName),
},
});
const loginInputMachine = Machine(createInputMachineConfig('login'));