While developing a complex ui with React I noticed that performance was being worse than expected. Following the official recommendations I started overriding shouldComponentUpdate and adding shallowCompare.
It turns out it was not enough to solve the problem. In a nested component that was rendering a list of items, adding a new element was causing the update for all of them (and not just them but their whole subtrees). Here it is a JsFiddle illustrating the problem. Look at the console when adding a new element.
The caveat is this:
1 |
{ "foo": "bar" } === { "foo": "bar" } // ==> false |
If the prop is an object but the references are not the same, then equality fails and it gets re-rendered.
One simple solution is to use simple props instead of objects. With the help of the spread operator from ES6 this is quite easy:
Another solution is to use an external library like Immutable.js that has a method to query data equality:
1 2 3 |
const map1 = Immutable.Map({ foo: 'bar' }); const map2 = Immutable.Map({ foo: 'bar' }); console.log(Immutable.is(map1, map2)); // ==> true! |
But it can only go so far. If a property/value of the object is a complex object like an array, data equality will still fail:
1 2 3 4 5 6 7 |
const map1 = Immutable.Map({ foo: 'bar' }); const map2 = Immutable.Map({ foo: 'bar' }); console.log(Immutable.is(map1, map2)); // true! const map3 = Immutable.Map({ foo: [1] }); const map4 = Immutable.Map({ foo: [1] }); console.log(Immutable.is(map3, map4)); // false! (╯°□°)╯︵ ┻━┻ |