user1360135
user1360135

Reputation: 67

createSelector of reselect: does it do deep comparison for nested object?

What if second(nested object) changes in redux? If it do shallow comparison it should ignore the change and not re-render.

All the example I see in doc, they are based on a simple object, where shallow compare is ok.

// assume state is:  {data: {first : {second { } } }}

const selectData = state => state.data;

const selectSecond = createSelector(
    selectData,
    data => data
);

Upvotes: 3

Views: 4558

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42188

createSelector uses strict equality (===), which means that two objects are considered "equal" if and only if they are references to the same object in memory. This the same type of check that React uses when comparing state or comparing useEffect dependencies.

Shallow equality means that two objects are equal if all of their properties are strictly equal.

Deep equality means that two objects are equal if their contents are the same, regardless of object references. It is computationally expensive and almost never needed in React or Redux due to the immutable nature of data.


Redux state is considered immutable so you should never have a situation where an object is the same reference in memory but has different contents. Every time that a property changes, you must create a new object. If second has changed, then first and data will be new objects.

What if 'second' (nested object) change in redux? If it do shallow comparison it should ignore the change and not rerender.

You would only have this problem if you made a mutation in your state. As long as your reducer is correct then you will get rerenders whenever state.data changes because any change at all requires creating a new object.


Here's a few examples of the various equality checks:

state => state

state is strict equal, shallow equal, and deep equal.

state => ({...state})

state is shallow equal and deep equal. It is not strict equal because it is a new object.

state => ({...state, nested: {...state.nested}})

state is deep equal. It is not strict equal or shallow equal because the nested property is a new object.

state => ({...state, number: 5})

state has a changed property so it fails all equality checks.

state => {
  state.nested.number = 5;
  return state;
}

This is the sort of mutation that is not allowed in React or Redux. state is strict equal because we returned the same state object. It is also shallow equal because state.nested is the same object. It is not deep equal (unless the value was 5 before).

state => {
  state.nested = 5;
  return state;
}

Again this is not allowed. If you mutate a top-level property then state is strict equal but not shallow equal or deep equal.

Upvotes: 9

Related Questions