When I click on one of my InspectorOption components, my redux logger shows that an action is dispatched and the state updates as expected.
My InspectorSelect and children InspectorOption components use react-redux's connect to mapStateToProps and these component depend on those props that come from state.
But even though the state is updating and the components depend on state, the components are not re-rendering when the state updates.
Why are my components not re-rendering when the state changes and how do I correct this?
@connect((state) => {
return {
options: state.inspector.options
}
})
export default class InspectorSelect extends Component {
render() {
return (
<div>
{
this.props.options.map(option => {
return <InspectorOption
option={ option }
key={ option.id }
/>
})
}
</div>
)
}
}
https://github.com/caseysiebel/dashboard/blob/master/src/components/InspectorSelect.js#L17
As @markerikson noted: 99.9% of the time, it's due to accidental mutation of Redux state in a reducer
There is a mutation in dashboard/src/reducers/inspector.js
export default function reducer(state = {
options: []
}, action) {
switch (action.type){
case 'SET_INSPECTOR':
state.options = state.options.map(option => { // <-- mutation here
return option.id === action.payload ?
{ ...option, active: true } :
{ ...option, active: false }
})
return state // returning mutated state
default:
return state
}
}
should be
export default function reducer(state = {
options: []
}, action) {
switch (action.type){
case 'SET_INSPECTOR':
var newOptions = state.options.map(option => {
return option.id === action.payload ?
{ ...option, active: true } :
{ ...option, active: false }
});
return {...state, options: newOptions} // returning new state
default:
return state
}
}