Closed alilee closed 2 years ago
Hi @alilee, you're not alone! Async during a reduction is a popular request, and we now have future support on master (https://github.com/intendednull/yewdux/blob/master/examples/future/src/main.rs), however the Reducer
trait specifically hasn't received this attention yet.
Adding a new, async version of Reducer
is not a problem. I'll get that working as soon as possible!
To be completely honest, async reductions have been a bit of a blind spot for me. I've always only updated application after a request, however I do see the utility of an async context during a reduction. Thanks for bringing it to my attention, will notify when ready!
For now I suggest a simple workaround:
enum Msg {
// The message send from your app
Action,
// The message you get after the server completes
ServerResponse(ServerResponse),
}
impl Reducer<MyStore> for Msg {
fn apply(&self, state: Rc<MyStore>) -> Rc<MyStore> {
match self {
Msg::Action => {
let state = { /* changes to local state */ };
spawn_local(async move {
let response = client.request(..).await;
Dispatch::<MyStore>::new().apply(Msg::ServerResponse(response));
});
state
},
Msg::ServerResponse => {
let state = { /* handle response */ };
state
}
}
}
}
As you've already discovered, you won't be able to mutate state inside of the async context. Instead I suggest creating a new dispatch that applies a dedicated message to handle the server response. This effectively places the async stuff between reductions, instead of during.
If you'd like further assistance with the particulars of your implementation, please feel free to reach out on the yewdux channel of the Yew discord. I (or anyone from that amazing community) can provide a more reactive support for you whenever needed!
Thanks very much for the clues - I'm seeing the way forward. I'll try and put a PR together for a very small example myself.
Thanks for this crate. I love the economy of your implementation - very impressive re-use of a small number of core concepts. It is hard to get my head around it, but can definitely appreciate the art.
I would like to make a
Store
likeRelation<X>
(a hashmap of uuids to X's) which has aReducer
which speculatively applies the change to the localStore
but also makes an asyncRequest
of theReducer
message to a remote server API (as a mutation) which would respond with the updated/persisted X (or maybe an error based on validation).Any thoughts about an example which puts the
Store
between yew and a server? Do you think it would be possible? My attempt has run into weird ownership issues with theStore
update inside aspawn_local
insideReducer::apply
.