-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Best way to avoid invoking promises multiple times (or keeping context up to date) #124
Comments
Another idea.. what if const save = (ctx, ev, send) => { // <-- notice send, a new param, enables async behaviours not just promises
send({ type: 'assign, saving: true })
post(ev.id, ev.data)
.then((data) => { send({ type: 'done', data }) })
.catch((error) => { send({ type: 'error', error }) })
}
const machine = machine({
saving: state(
immediate('saving', guard(ctx => !ctx.saving), action(save)),
transition('done', 'closing', action(close)),
transition('error', 'configure', reduce(assign)),
transition('close', 'closing', action(close)),
assignable('saving'),
)
}) |
Just for reference Xstate supports this in the following way. const machine = createMachine({
states: {
idle: {
on: {
load: 'loading',
}
},
loading: {
src: 'fetchData',
onDone: 'idle',
on: {
assign: {
actions: [
// Perform updates during invocation
]
}
}
},
}
}); It also supports it via I believe this could be addressed if the library allows const assign = (ctx, { type, ...data }) => ({ ...ctx, ...data })
const assignable = name => transition('assign', reduce(assign));
const machine = createMachine({
saving: invoke(
save,
transition('done', 'closing', action(close)),
transition('error', 'configure', reduce(assign)),
transition('close', 'closing', action(close)),
assignable('saving'), // <--- Works now
),
}) A different name might be more fitting as it is no longer a transition and basically an event listener, Update: got it working with the export |
Hi, thanks for a great library, been enjoying learning to use it.
I don't know how common this is, but I want to keep various bits of data (props, data from other hooks) in the context and I want to keep them up to date even if I'm in a middle of invocation.
To do so, I've added an 'assign' transition to every state:
A few thoughts / questions / learnings from this so far:
onClose
function passed via prop, or some other bits of context), wondering if there should be an easier way to update the context (in xstate, I think you can do that by handling an even in the root machine).assignable
call. Wondering if self transitions could be made easier.. Or perhaps the first problem is solved in a different way, this would also go away.I'm not really saying these are even a problem, I think it's good to be explicit and keep the rule set small and simple.
But the next bit is more challenging. The issue is that if you're in the
saving
state and send 'assign' event to update context (if say the parent component rerendered passing a newonClose
prop), you invoke thesave
function again, but we don't want that in this case of self transition. Now, the best way I found so far to avoid this was to create a custominvokeOnce
helper, which only invokes the function on entering the state and not on "self" transitions:Only sharing all this to get feedback from any current / future users of robot about how they handle this sort of stuff.
For example, would it be better if invoke always triggered on enter only, and to allow invoking multiple times you'd have to transition out and back in?
Or should there be a way to guard an invoke? (not sure that's semantically correct).
Or perhaps another way would to solve this is to use an intermediate state:
The text was updated successfully, but these errors were encountered: