|
|
|
|
|
by philmander
3766 days ago
|
|
Taking Redux, for example; doesn't a Redux store's getState, dispatch and subscribe methods roughly map to a Backbone model's get, set and on methods respectively? Isn't the immutabability of data in a redux store an implementation detail of the store? How does this impact the React views? |
|
This adds more ceremony around changing the state but in my experience (I’m biased: I wrote Redux) makes such changes easier to debug and test.
Every change comes as an action that the whole reducer tree can handle, so changes are predictable and reproducible if you record actions. You can change how actions are handled without changing the components dispatching them. A good example is how your components can emit SHOW_NOTIFICATION action but you can refactor your reducers from allowing only a single notification at the time to keeping a stack of notifications, without changing any of the components emitting them. This is what separating actions from state changes gives you.
You can log every action and see the entire state tree before and after the action. This, in my experience, makes it easier to fix incorrect mutations spanning across multiple entities. If the user clicks a button and the state is updated, and then a network response comes, and the state is updated again, you can log diffs between the state changes and have a clear picture of everything that’s happened. In fact Redux DevTools even provide a UI for that, e.g. https://github.com/alexkuz/redux-devtools-inspector.
One feedback I hear particularly often about Redux is that people who never wrote unit tests for front-end apps started writing them because it is just so easy to test reducers. You don’t need to mock any dependencies or simulate AJAX requests because any new data (whether local or remote) comes in the form of actions. So you can just call the reducer with a state and an action, and assert that its output matches what you expect.
With a single state tree I found it easier to ensure that all state is normalized and you don’t have duplicate data. In Backbone, it is encouraged that models are instantiated as you parse the request which makes it non-trivial to normalize them and merge the changes. In Redux, any merging is going to be explicit, and you can always inspect the single state tree to make sure the structure is normalized and matches what you expect it to be.
By contrast, in Backbone, models are active records so user.followUser(anotherUser) will set() a few flags on itself, fire off an async request, set() fields on another model, then possibly revert if the request failed. This is pretty hard to do consistently because there is no central point to mutations. You also have to build some sort of cache and entity resolve mechanism to make sure you don’t have duplicate out-of-sync models describing the same data.
Finally, in Redux mutations are forbidden so it is easy for the views to bail out of reconciliation if the corresponding state fields have not changed. In my experience, Backbone doesn’t make such optimizations easy because it was designed with completely mutability in mind.
So Redux, in a way, is similar to Backbone, but also is very different.