3 ms·
Why do we need Immer? Can't we just do our object copying ourselves? It seems using Immer it can break dev's intuition about pass by reference and performance.
by christiansakai 6y ago
Why do we need Immer? Can't we just do our object copying ourselves? It seems using Immer it can break dev's intuition about pass by reference and performance.
- acemarke 6y agoYou don't _need_ Immer. But: - Writing immutable update logic by hand is really hard to do correctly and hard to read - Accidental mutations have historically been the number one cause of bugs in Redux apps Immer eliminates accidental mutations, and makes it _way_ easier to write and read code that does correct immutable updates. So, we now recommend Immer as the right way to do immutable updates in Redux [0], and Redux Toolkit uses it by default [1]. Agreed that there is absolutely a learning curve aspect here - you need to know why and how to write immutable updates by hand to really appreciate what Immer is doing for you, which is why I've repeatedly highlighted that information in our docs [2]. [0] https://redux.js.org/style-guide/style-guide#use-immer-for-writing-immutable-updates https://redux.js.org/style-guide/style-guide#use-immer-for-w... [1] https://redux.js.org/tutorials/fundamentals/part-8-modern-redux#immutable-updates-with-immer https://redux.js.org/tutorials/fundamentals/part-8-modern-re... [2] https://redux-toolkit.js.org/usage/immer-reducers https://redux-toolkit.js.org/usage/immer-reducers
- pgsandstrom 6y agoMaybe Im missing something, but why not simple do a deep clone of the state object and then modify the deep clone?
- acemarke 6y agoA deep clone is _not_ what you want here. A correct immutable update is better described as a "nested shallow clone", where you copy each specific level of nesting from the root down to the value(s) you actually want to change. A deep clone would result in unnecessarily copying a bunch of extra objects and arrays that aren't relevant, so that's a waste of cycles. On top of that, the React ecosystem (and React-Redux in particular) relies on reference comparisons to determine if data has changed. If you copy objects that didn't actually get updated, it can cause a lot of components to re-render when they really shouldn't have. For more details see: - Dave Ceddia's "Complete Guide to Immutability in React and Redux": https://daveceddia.com/react-redux-immutability-guide/ https://daveceddia.com/react-redux-immutability-guide/ - The Redux docs page on "Immutable Update Patterns": https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns https://redux.js.org/recipes/structuring-reducers/immutable-... - The Redux FAQ entry on deep cloning: https://redux.js.org/faq/performance#do-i-have-to-deep-clone-my-state-in-a-reducer-isnt-copying-my-state-going-to-be-slow https://redux.js.org/faq/performance#do-i-have-to-deep-clone... - The Redux FAQ page on immutability: https://redux.js.org/faq/immutable-data https://redux.js.org/faq/immutable-data
- IceHegel 6y agoThis will work but isn't advised. - Bad: newX = JSON.parse(JSON.stringify(x)) - Slightly Better: newX = lodash.cloneDeep(x) - Best(using immer): newX = produce(x, draftX => {draftX[1].done = true}) I don't know how JavaScript engines actually assign memory, but I think of object references in JavaScript like pointers in C. If you deep clone you're copying way more than you need, mallocing giant blocks of memory for duplicated data. Libraries like immer(the best) and immutable.js will only copy what you changed, which saves time and memory.