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'));
Maybe that happens because dirty
is a final state, for example:
{
id: 'loginForm',
initial: 'idle',
context: {
error: undefined,
},
invoke: [
{
id: 'usernameInput',
src: inputMachine,
},
{
id: 'passwordInput',
src: inputMachine,
},
{
id: 'loginButton',
src: buttonMachine,
},
],
states: {
idle: {
},
processing: {
},
finished: {
},
failed: {
},
},
};
I have this machine which spawns some actors, and I can access through loginForm
machine in the following way loginForm.state.children.usernamInput
, but if one of those machines have reach a final state it returns undefined.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.