3 ms·
Immer looks awesome but we're relying on Immutablejs shallow object comparison to stop rendering React components when not needed. When I last checked I could n
by k3liutZu 7y ago
Immer looks awesome but we're relying on Immutablejs shallow object comparison to stop rendering React components when not needed. When I last checked I could not figure out how to achieve the same thing with Immer.
Do you know some reference that addresses this?
And if we're here an additional question: since our store data is currently composed of deep immutable JS data structures, do you know of a way to slowly migrate to Immer?
I've tried to move parts of the store to Immer, but since the root store obejcts are still Immutable js objects, this didn't go well.
- acemarke 7y agoShallow object comparison is not a special property of Immutable.js. It's just a matter of iterating over the keys and values of two objects and comparing them. In fact, that's how React-Redux (and many other React ecosystem libs) work. `connect` decides whether to re-render your component by doing shallow comparisons of the previous and current `mapState` return object to see if the extracted values have changed. All that's necessary is to do immutable updates of your data, by always making _copies_ of the data and modifying the copies (see [0] and [1] for discussions of immutable updates). It doesn't matter whether the new object references were produced by manually creating copies ( `{...obj}`, `someArray.map()`, etc), by using Immutable.js's API, or Immer tracking the "mutations" via a proxy and creating the new references internally. As long as you have immutable updates and new references, shallow comparisons work fine. So, there's nothing special you need to do to make Immer work with comparisons. You literally just use it as described in the docs. Specifically for comparisons, `PureComponent` and `React.memo()` both do shallow comparisons of `props` by default. Yes, the pervasiveness of Immutable.js's API is one of the reasons I've long suggested that folks avoid it [2]. I don't have any detailed suggestions for migrating, other than perhaps consistently using Reselect selectors to encapsulate reading values from the store and handling the Immutable.js -> `toJS()` conversion (which you should probably be doing anyway as a perf optimization, since that conversion is relatively "expensive"). That way, as you switch over chunks of reducer logic from Immutable.js to Immer, the code consuming those values _should_ still be getting POJOs out of the selectors, with no actual visible change. [0] https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns https://redux.js.org/recipes/structuring-reducers/immutable-... [1] https://daveceddia.com/react-redux-immutability-guide/ https://daveceddia.com/react-redux-immutability-guide/ [2] https://www.reddit.com/r/javascript/comments/4rcqpx/dan_abramov_redux_is_not_an_architecture_or/d51g4k4?context=3 https://www.reddit.com/r/javascript/comments/4rcqpx/dan_abra...
- thebosz 7y agoImmerJS is a direct replacement for ImmutableJS. We recently switched from using ImmutableJS in our Redux store to using ImmerJS. We took the approach one reducer at a time. We have multiple reducers and we're using combineReducers (the ImmutableJS one until it was completely converted). We had no issues whatsoever in the change. ImmutableJS doesn't care about plain JS objects (which is what ImmerJS reducers return) so everything worked as expected. React's shallow comparison worked as expected since ImmerJS produces new objects on mutation (just like ImmutableJS). Essentially: there is no case where ImmutableJS is needed. All functionality and benefits are available in ImmerJS which is a much easier to use library. To do the migration, we literally just used the docs on the Github repo. This was back with version 1.0 or something and it wasn't documented very well but we were able to figure it out. The first code example is how to use it with Redux. Also the section on Currying is useful. Edit to add: This is all within the context of web apps, specifically React apps with Redux. I'm sure there's probably some places where ImmutableJS is desirable, but I don't know of any.
- __s 7y ago"there is no case" is a strong statement. ImmutableJS is generally the wrong tool for the job in a reducer. It's optimized for if you have a single flat object with 1000s of keys. Immer can't implement the same level of structural sharing
- thebosz 7y agoI added a caveat.
- aidos 7y agoCan you explain this scenario further? I’ve not used immutablejs but I’m familiar with both functional data structure concepts and immerjs. Immerjs just improves the ergonomics updating a native nested structure in a way that the original contents are maintained as much as possible. Because js has dreadful support for equality checks, this definitely comes in useful.
- 7y ago