Reputation: 7016
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.
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?
Upvotes: 1
Views: 1100
Reputation: 7016
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.
Upvotes: 0
Reputation: 6803
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
Upvotes: 1