5 ms·
Pros and Cons of using immutability with React.js
- wesbos 11y agoVery well written - great job!
- straws 11y agoThere's a benefit to teasing apart two ideas here: - writing functions that expect immutable data (you get referential transparency and value equality → a system that's easier to reason about) - using persistent data structures (makes it cheap and efficient to create new changes to your data over some messy Object.assign helpers) Javascript doesn't promote applications written in that style though, so you're definitely going to want to use a library like Immutable.js everywhere for those kinds of guarantees.
- dustingetz 11y ago> I’d recommend the immutable-js library for it. It has nice API and it comes from Facebook itself. Another option is the baobab library - but it works better when more ‘reactish’ ideas are present in your codebase, like global app state. Another option is a library I wrote, react-cursor[1], which is basically sugar over the React immutability helpers[2] which the article mentioned. react-cursor has a couple advantages over immutable-js and baobab: 1/ simpler types: use regular react state with plain old js data structures, 2/ simpler implementation - about 100 lines of code and tiny api, 3/ super easy to integrate with your existing large codebase already using react state [1] https://github.com/dustingetz/react-cursor https://github.com/dustingetz/react-cursor [2] http://facebook.github.io/react/docs/update.html http://facebook.github.io/react/docs/update.html
- rattray 11y agoFor those looking for great Flux libraries with immutability at their core, I've been loving NuclearJS[0], which is built on top of ImmutableJS and untangles your stores by giving you a great kind of "functional lens" called Getters. One problem I have is that ImmutableJS[1] doesn't list the complexity of any of the operations in their documentation. So it can be hard to intuit the efficiency of given operations without having read/grokked the 5k sloc of source. [0] https://optimizely.github.io/nuclear-js/ https://optimizely.github.io/nuclear-js/ [1] https://facebook.github.io/immutable-js/docs/ https://facebook.github.io/immutable-js/docs/
- danmaz74 11y agoWe've started using Redux [1] lately, because we found some flaws in the original Flux architecture [2]. We also started using ImmutableJS together with Redux. Would you care to list any advantages of NuclearJS over Redux? [1] http://gaearon.github.io/redux http://gaearon.github.io/redux [2] biggest flaw: if an action updates two different stores, and a component depends on both stores, the component will get rendered twice. Even worse, the first time it will get rendered with one store updated and the other one not updated, so possibly in an inconsistent state.
- rattray 11y agoThe biggest gap I was previously aware of in Redux was the lack of getters, but as bryanlarsen points out in a sibling to your comment, that appears to be available in reselect: https://github.com/faassen/reselect https://github.com/faassen/reselect (last time[0] I talked about Nuclear vs Redux here, reselect didn't have a readme). So I'll need to take some time to evaluate the options... [0] https://news.ycombinator.com/item?id=9833058 https://news.ycombinator.com/item?id=9833058
- danmaz74 11y agoThanks for the reply. The philosophy for Redux seems to keep the core as agnostic as possible, and that's why getters are outside of core. In part I like this, in part I don't - for sure it makes it difficult to evaluate it, as there are so many possibilities... I think I wouldn't mind some more convention over configuration.
- bryanlarsen 11y agoIf you want the getters functionality in redux, use reselect: https://github.com/faassen/reselect https://github.com/faassen/reselect At this point I really get the impression that redux has "won" now that flummox recommends using redux instead of flummox. Flux libraries are small and simple enough that it probably won't hurt to use a non-mainstream flux library, but it's probably still best to use the same one everybody else is using.
- 11y ago
- skybrian 11y agoOkay as far as it goes but it downplays some difficulties. A con when updating tree structures is the need to replace all nodes along the path from the root, which is why functional languages sometimes use fancy data structures like lenses. Graphs are a bit awkwardly represented (can't use regular pointers due to cycles). Reference comparisons are fast for small nodes, but for something like a large list, it's often not enough to know it was touched. You need to compute the diff to make updates efficient, which often requires a linear scan or worse. Making this efficient for arbitrary list mutations is a fairly difficult problem.
- klibertp 11y ago> fancy data structures like lenses I think you mean zippers. I'm not sure if lenses can be called data structures. They are closer to Functors than say Linked Lists in nature (but I may be wrong here).
- couchand 11y agoThis is a good overview article with lots of practical examples. One nit. These lines are written many times: x == y; // true x === y; // true without a single instance where the results differ. This would be stronger if the first line of every pair were removed, since this isn't an article about JS equality operators.
- k__ 11y agoThis week I learned to love the spread operator. const newState = {...state, ...objectWithNewValues}
- andrewstuart2 11y agoWhoa, that works on objects/properties? I hadn't seen that before. That's nice.
- k__ 11y agoYes, here some simple examples: (state, action) => ({...state, loading: true}) (state, {error}) => ({...state, error, loading: false}) (state, {result:{data}}) => ({...state, ...data, loading: false})
- lowboy 11y agoJust keep in mind that object spread operators are a TC39 stage 1 proposal at this point.
- smrq 11y agoThat's really cool. Worth noting that it's an ES7 proposal rather than part of ES6, so you get it with Babel but not native ES6, or e.g. TypeScript.
- wereHamster 11y agoObject.assign does not work well when you have classes. For one of my projects I came up with a small helper to clone class instances: https://caurea.org/2015/07/19/generic-immutable-objects-in-javascript.html https://caurea.org/2015/07/19/generic-immutable-objects-in-j.... In addition to cloning, it freezes the new object so accidental attempts to mutate it will throw an exception (in strict code).
- rymndhng 11y agoImmutability doesn't have to be a discipline. It is the default when working with ClojureScript!
- mcphage 11y agoThe author's primary motivating example is the high cost of deep equality checks. I'm not sure how immutability helps with that; yes, if two variables are === then they havn't changed, but two objects can be !== but still value equal. So if you want to know if two objects are (value) equal, you'll still need to check.
- baddox 11y agoThe primary use case for checking equality in React is when you change one part of your application state and it triggers a rerender of a large React component tree. Since you probably only changed one small bit of the state (e.g. you created a new todo list item), you don't actually need to rerender unrelated components (e.g. the already-existing todo list items). Immutable data allows you to do cheap (constant time) reference equality checks, because the data objects representing the existing todo list items will be the exact same objects that they were previously. In this fundamental React render flow, you probably won't need to worry about checking value equality between two different objects if you are using immutable data. Now, your application might have specific UI requirements that need to do value equality. As a random example, you might have a complex form, and you might want to know if, after the user changed several things, the form's data is different than it was at the beginning. In this case, you'll have to do a (more expensive) value equality check.
- danmaz74 11y agoWith React, the point is that by simply comparing the reference to immutable objects you can skip most unnecessary re-renders almost for free. Of course you'll still have some false positives (ie, the reference is different but the content is the same, and re-rendering wasn't necessary) but that's not a big penalty.
- munro 11y agoImmutability for stateful things seems unintuitive at first, but reframed as the lack of mutability, it makes more since. We can easily add it. yourCar === neighboursCar; // false yourCarRepainted === yourCar; // false :( In the article's examples, how does the program know which object is different? It's weaved into the language design that every object has an address. That means if we want to write code without mutability, the interpreter has no idea since mutability is always on, and can't protect from accidentally modifying intentionally stateless code. Flip side, if immutability is the default, we can easily add state, since it's just a lack of an address. The address becomes part of the data structure, giving the coder more power, since it's not locked outside of the code. Think SQL! Or Haskell! var yourCar = {id: 'my_car', color: 'red'}, neighboursCar = {id: 'neighbours_car', color: 'red'}; function referenceEqual(a, b) { return valueEqual(a.id, b.id); } referenceEqual(yourCar, neighboursCar); // false :D var yourCarRepainted = Object.assign({}, yourCar, {color: 'red'}); referenceEqual(yourCar, yourCarRepainted); // true :D Notice we've now flipped the address into our data, and even the (===) operator in our hands. With JS, this will run slowly since it can't infer our immutability, but constants are coming!
- JDDunn9 11y agoSeems like the biggest benefit to immutability is that it reduces the time spent dirty checking objects. So if you use getters/setters instead of dirty checking, immutability doesn't provide much benefit right?
- gcb0 11y agoso let's use tons more memory and slow copies by value everywhere, not to mention backward coding, just because our generic UI framework is too generic?
- stevebmark 11y agoThere is a lot of good information here, but being a stickler for detail, I found the frequent grammar errors distracting. It seems like with all the self-advertisement conversion signup forms, it would be helpful to have an editor, or a native speaker of the language it's written, go over it.