What I've realised recently is, this is basically event sourcing. Replace actions with events, selectors with projections, and memoization with snapshots. So this submission is certainly timely and of interest to me. Thanks!
You can go even further and use the exact same "events" or "actions" for event sourcing on the server side too. You just need to save the list of actions to the server. This lets you do realtime sync and multiplayer really easily!
It makes Implementing CQRS in a single service really easy. GETs load the event log, replay and display the results while POSTs send a command that gets translated into an event. If it is valid it gets appended to the log. This approach is storage agnostic: It doesn’t matter how the log ultimately gets stored
That's another nice way of doing things that way, better diagnostics eh?
A list of all past states avoids the determinism problem, but the consequence of each action is only implicit in the difference between two states.
For event sourcing, "the state" is the list of events, and what you're calling "the state" is just another selector/projection.
Got any examples of this?
Also, how do you feel it's better than a typical Redux app setup?
As it moves all the focus from reducers to selectors, and has quite different requirements for how to do caching there, it’s led me to work on a custom selector library with quite different API from reselect/re-reselect. I’d like to release it when my experiments start to feel... less experimental.
But y'all must be storing this `(point-in-time-state, action-that-produced-state)` somewhere, because the Redux Chrome plugin displays this data. Was I wrong in thinking the Chrome plugin was just visualizing data already stored by Redux?
function createStore(reducer) {
var state
var listeners = []
function getState() { return state }
function dispatch(action) {
state = reducer(state, action)
listeners.forEach(listener => listener())
}
}
It's the Redux DevTools that do the real work of actually saving an action log, like what was described above. In fact, canceling actions does actually work by re-running the actions in the same sequence, minus the ones that are being skipped, to generate the new state.That logic has been split out into its own package, which you can see in the https://github.com/zalmoxisus/redux-devtools-instrument repo.
Very vaguely related side note: earlier this year, I spent a couple days to add an "action stack trace" tab to the Redux DevTools Extension. When you click on an action, in addition to seeing the action contents, state tree, and diff, you can now also see an actual formatted stack trace that shows you exactly where the action was dispatched from (including the actual code if you've got sourcemaps enabled). Sadly, the extension maintainer has been MIA recently, so we're considering forking it into the Redux org. Until then, you can download my custom build of the extension here: https://github.com/zalmoxisus/redux-devtools-extension/issue...
edit: Here's the link where it's implemented in redux-devtools if anyone else is curious https://github.com/reduxjs/redux-devtools/blob/master/src/cr...
https://medium.com/@jamestthompson3/beyond-counters-using-re...
https://medium.freecodecamp.org/how-to-build-a-github-search...
https://twitter.com/gabrielvergnaud/status/10573757954155233...
[1] maybe this talk? https://www.youtube.com/watch?v=JHGkaShoyNs