1
votes

In simple todo list application, I have FiltersContainer component, which provides props to Filters component:

// FiltersContainer.js
import { connect } from 'react-redux';
import { setVisibilityFilter } from '../actions';
import Filters from '../components/Filters';

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

  // `visibilityFilter` variable value is - 'SHOW_ALL'.
  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',
    }],
  };
}

function mapDispatchToProps(dispatch) {
  return {
    onFilterClick(value) {
      dispatch(setVisibilityFilter(value));
    },
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Filters);

The problem is, that this component renders everytime state changes.

For example, toggling todo item forces rendering <Filters /> component, although filters array and visibilityFilter hasn't changed.


If replace filters array in mapStateToProps function with string, this component would not be rendering on every state changes:
// FiltersContainer.js
function mapStateToProps(state) {
  const { visibilityFilter } = state.todos;

  return {
    filters: '',
  };
}

Full application code is available at - https://github.com/1ven/react-redux-todos

Am I missing something?

2

2 Answers

1
votes

EveryTime you are returning a new Object from mapStateToProps thats why old props are not equal to the new props. Hence the component gets rendered everytime

React render the component if old props are not equal to new props In your case you do

 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',
    }],
  };

oldProps = object

newProps = another object (although content is same both are different objects )

oldprops==newprops //no rerender

When you do

return {
    filters: '',
  };

oldprops = ''; newprops = '' oldprops === newprops dont render

0
votes

The problem was in shallowEqual util function, which uses react-redux library to check whether component props changed.

This function does not makes deepEqual checking, it only makes shallow checking, thats why object, which contains property with array is not equal to the same object.