RFC: New effect & update Signature
See original GitHub issueRequest for comments for new update
signature inside effect.
@RunDevelopment, @dani-mp, @RichieAHB, @icyJoseph, and anyone interested.
Problem Statement
One issue we currently have within effects is that even though send
and update
are different functions, they’re frequently used together (update the context, then trigger a transition). E.g.:
effect(send, update) {
const fetchData = async () => {
let response: Response;
try {
data = await someApi();
update(context => ({ ...context, data: data }));
send('SUCCESS');
} catch (error) {
update(context => ({ ...context, error: error.message }));
send('FAILURE');
}
};
fetchData();
}
Proposal (Updated)
The proposal is to pass a new assign
parameter to effect
. It’s a function that takes an Object as argument with the type:
{
update?: (context: Context) => Context;
event?: EventString | EventObject<EventString>;
}
The above fetch example would look like this:
effect(assign) {
const fetchData = async () => {
let response: Response;
try {
data = await someApi();
assign({update: context => ({ ...context, data: data }), event: 'SUCCESS'})
} catch (error) {
assign({update: context => ({ ...context, error: error.message }), event: 'FAILURE'})
}
};
fetchData();
}
Proposal (Old)
The proposal is to keep passing both send
and update
(as well as event
, in the future) to effect
, BUT with one change: update
will also return send
, so you can couple updating the context and sending event on a single line:
update(updaterFn)('SUCCESS');
Granted, it might look a little weird at first, but it has a few advantages:
- You can still just
send
or justupdate
(keep a simple API and backward compatible) - It relates to how the state machine is configured (curried function, context first, state machine second) - can aid learning/remembering the API because it’s mnemonic.
Alternative Considered
We could remove the update
method from effect
and overload send
to also update the context:
send(event: string)
send(event: string, updater: fn)
send(updater:fn)
I see a few disadvantages here:
- Send would have many different overloaded signatures, which could be confusing.
- Since we don’t want to allow free mutations of the context outside an effect, the
send
method insideeffect
would be different from thesend
returned when calling useStateMachine. We might need to come up with different nomenclature or incur the risk of making the API confusing.
Thoughts? Ideas? Comments?
Issue Analytics
- State:
- Created 2 years ago
- Comments:16 (9 by maintainers)
Top GitHub Comments
I could try to take on the partial updates some time later on, if not done by then.
Well, it is worth exploring all alternatives, but at the end of the day, specially named keys might just be the solution.
Updated the proposal