I've been working with optimistic updates in a React+Flux application and saw two things:
So I work on this and create an ActionStore to manage the state of the actions triggered by the components. Here is the source code and here is a live demo.
It works more or less like this:
I've done this mainly for separate the state of the "entities" from the state of the actions, but allows retrigger actions with the same payload too (this could be useful when we receive 500 response status if the server is temporarly down or if the user loose signal).
Also, having an store of actions allows to easily ask if they are pending actions before the user logout or close the window.
Note: I'm working with a Single Application Page web app against a Rest API, I'm not think to use this on server-side rendering
It's a viable option create a ActionStore or I'm breaking some Redux/Flux foundations? This could end the posibility of use React Hot Reloading and Time traveling?
You should answer with no mercy, I've probably done a bunch of ugly things but I'm learning React/Redux.
To the future readers who might be a little bewildered: we don't call these functions “stores” anymore: we call them reducers. So the question is about a reducer remembering actions.
Personally I don't like the approach you're suggesting there. You're putting logic into actions and using inheritance for this. On the contrary, Redux prescribes actions to be plain objects without logic. They shouldn't “know” how to update some state, and they shouldn't hold it—instead, they should describe what happened.
I think the approach for implementing optimistic updates in Redux is similar to how you'd implement Undo in Redux, which in turn is inspired by Elm architecture. The idea is that you should write a function that takes a reducer (and some options) and returns a reducer:
function optimistic(reducer) {
return function (state, action) {
// do something?
return reducer(state, action);
}
}
You'd use it just like a normal reducer:
export default combineReducers({
something: optimistic(something) // wrap "something" reducer
})
Right now it just passes the state and action to the reducer
it wraps, but it can also “remember” actions:
function optimistic(reducer) {
return function (state = { history: [] }, action) {
// do something with history?
return {
history: [...state.history, action],
present: reducer(state.history[state.history.length - 1], action)
};
}
}
Now it accumulates all actions in the history
field.
Again, this by itself is not very useful, but you can probably see how you can implement such higher order reducer that:
status: 'request'
;status: 'done'
, resets the history;status: 'fail'
, adjusts the history to not include the initial action with status: 'request'
and re-runs the reducer to re-calculate the present state as if the request never happened.
Of course I haven't provided the implementation, but this should give you an idea of how to implement optimistic updates in a Redux way.
Update: as per the OP's comment, redux-optimist seems to do exactly that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With