React-redux: Use shallowEqual comparison instead of deepEqual in shouldComponentUpdate.

Created on 11 Jul 2016  路  2Comments  路  Source: reduxjs/react-redux

I have FiltersContainer component, where mapStateToProps function returns object with prop, which contains array:

function mapStateToProps(state) {
  const { visibilityFilter } = state.todos;

  return {
    filters: [{
      title: 'All',
      value: 'SHOW_ALL',
      active: visibilityFilter === 'SHOW_ALL',
    }, {
      title: 'Completed',
      value: 'SHOW_COMPLETED',
      active: visibilityFilter === 'SHOW_COMPLETED',
    }, {
      title: 'Active',
      value: 'SHOW_ACTIVE',
      active: visibilityFilter === 'SHOW_ACTIVE',
    }],
  };
}

This component is updating everytime state changes, although filters array wasn't changed.

As I understand shallowEqual function does not deeply comparing two objects and will return false this way, therefore Filters component is updating on every state change.

Why lib uses shallow comparing for mapStateToProps function result instead of deepEqual comparing? Or I'm missing something?

Thanks.

Most helpful comment

@1ven This is caused because of referential inequality. You always create new instance of Array therefore shallowEqual consider those two arrays different even the structure is same.

But the problem is deeper - you absolutely don't have to return whole filter structures from mapStateToProps as they seem to be constant. Instead, just have this config statically on module level. And from store, expose only activeFilter property. then you can have comparison like activeFilter === 'SHOW_ACTIVE' in render() method.

All 2 comments

Figured out, the answer is in redux docs.

@1ven This is caused because of referential inequality. You always create new instance of Array therefore shallowEqual consider those two arrays different even the structure is same.

But the problem is deeper - you absolutely don't have to return whole filter structures from mapStateToProps as they seem to be constant. Instead, just have this config statically on module level. And from store, expose only activeFilter property. then you can have comparison like activeFilter === 'SHOW_ACTIVE' in render() method.

Was this page helpful?
0 / 5 - 0 ratings