I have a List
component that displays multiple Item
components. List
gets its data from the Redux store.
When the store is up
A little bit of prior art (as Dan Abramov likes to say): Redux is a state management tool. It provides a HOC (connect
), but that HOC is not responsible for component management. Redux does not manage your component's lifecycle in anyway: it provides a means to efficiently store and query data your app needs. It's largely influenced by the Om, a Clojurescript bridge to React. In fact, store
s in redux very much resemble the atom
data type in Clojure.
Now, getting into the meat of your problem -- even if your data is exactly the same, and even if you did use shouldComponentUpdate
, your component is still going to re-render. The reason is that Array.prototype.map
always produces a new object on the heap. As a result they're not referentially equal. Some code to demonstrate this concept:
const myArr = [1, 2, 3]
const myArrCopy = myArr.map((n) => n);
myArr === myArrCopy // false
But if we use shallowEqual
, we get a different result:
const myArr = [1, 2, 3]
const myArrCopy = myArr.map((n) => n);
React.addons.shallowCompare(myArr, myArrCopy); // true
Why is that? That's because shallowCompare
checks for value equality, comparing each value in the arrays. However, shallowEquals
contains a potential pitfall for the uninitiated:
const myObject = { foo: 'bar' };
const myObject2 = { foo: 'baar' };
React.addons.shallowCompare(myObject, myObject2); // true
Our two objects aren't the same, but shallowCompare
returns true
because it only compares the keys of its arguments. If that's good enough for you, you can simply extend React.PureComponent
, which implements shouldComponentUpdate
for you, and uses shallowCompare
to compute equality of props
and state
.
Enter Immutable.js. This does away with the need for shallowCompare
entirely. Consider the following:
const myList = Immutable.List([1, 2, 3]);
const myListCopy = myList.map((n) => n);
myList.equals(myListCopy) // true
Internally, Immutable shares data, and can very efficiently compare data structures for deep equality. That being said, Immutable comes with trade-offs: data structures become much more opaque and can be more difficult to debug. All in all, I hope this answers your question. JSBin here: https://jsbin.com/suhujalovi/edit?html,js,console
{items.map((item, index) => <Item key={index} name={item.name} />)}
This line make always a new Array in the parent component, producing 'new' Item components every time