Skip to content

Instantly share code, notes, and snippets.

@robrobbins
Last active March 19, 2020 19:13
Show Gist options
  • Save robrobbins/d74edc6992f8ba8fce1314995b3c7952 to your computer and use it in GitHub Desktop.
Save robrobbins/d74edc6992f8ba8fce1314995b3c7952 to your computer and use it in GitHub Desktop.
a user state machine that should transition to either "registered" or "guest" via a guard...
// User may be in one of:
// * idle: no user. no registration or access attempts
// * guest: a present user, not registered or registration/access failed
// * registered: existing user
// * processing: a register/access fetch machine is in flight
const machine = Machine({
id: 'user',
initial: 'idle',
context: {
id: undefined,
email: undefined,
name: undefined,
fetchResource: undefined,
fetchOpts: undefined,
error: undefined,
},
states: {
idle: {},
guest: {},
registered: {
entry: 'registered'
},
processing: {
invoke: {
id: 'fetch',
src: fetch,
data: {
resource: ctx => ctx.fetchResource,
opts: ctx => ctx.fetchOpts
},
onDone: [{
target: 'registered',
cond: 'userRegistered',
actions: 'fetched'
}, {
// an unregistered user
target: 'guest'
}]
},
entry: send(ACTIVATE, { to: 'fetch' })
},
},
on: {
REGISTER: {
target: 'processing',
actions: 'register',
},
ACCESS: {
target: 'processing',
actions: 'access',
},
}
}, {
guards: {
userRegistered: (_, e) => !!e.data.id,
},
actions: {
register: assign({
email: (_, e) => e.email,
fetchResource: (_, e) => e.fetchResource,
fetchOpts: (_, e) => e.fetchOpts,
}),
access: assign({
// would have to be some auth/password or something... TBD
email: (_, e) => e.email,
fetchResource: (_, e) => e.fetchResource,
fetchOpts: (_, e) => e.fetchOpts,
}),
fetched: assign({
id: (_, e) => e.data.id,
name: (_, e) => e.data.name,
error: (_,e) => e.data.error,
}),
registered: ctx => {
console.log(`user ${ctx.id} registered`);
}
}
});
@robrobbins
Copy link
Author

robrobbins commented Mar 19, 2020

snippet from a spec that never goes beyond the "processing" state...

const listener = state => {
  if (state.matches('registered')) {
    expect(state.context.id).toBe('abc-123');
    done();
  } else if (state.matches('guest')) {
    console.warn('in guest state');
    done();
  } else {
    console.warn('IDK...');
    console.log(state.value);
  }
};
service.onTransition(listener);
service.send(REGISTER, { email: '[email protected]', fetchResource: '/users/new' });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment