I have the following reducer in React Redux:
export const reducer = (state = initialStateData, action) => {
switch (action.type) {
case Action.TOGGLE_ARR_FILTER:
{
const subArr = state.jobOffers.filters[action.key];
const filterIdx = subArr.indexOf(action.value[0]);
const newArr = { ...state.jobOffers.filters
};
if (filterIdx !== -1) {
newArr[action.key].splice(filterIdx, 1);
} else {
newArr[action.key].push(action.value[0]);
}
return {
...state,
jobOffers: {
...state.jobOffers,
filters: {
...newArr,
},
},
};
}And this is my object:
const initialStateData = {
jobOffers: {
filters: {
employments: [],
careerLevels: [],
jobTypeProfiles: [],
cities: [],
countries: [],
},
configs: {
searchTerm: '',
currentPage: 1,
pageSize: 5,
},
},
};The reducer as such seems to work, it toggles the values correctly.
But: Redux always shows “states are equal”, which is bad as it won’t recognize changes.
Can someone help ? I assume that I am returning a new object..
Advertisement
Answer
Although you take a copy of state.jobOffers.filters, this still holds references to original child arrays like employments. So when you mutate newArr[action.key] with splice or push, Redux will not see that change, as it is still the same array reference.
You could replace this:
if (filterIdx !== -1) {
newArr[action.key].splice(filterIdx, 1);
} else {
newArr[action.key].push(action.value[0]);
}
with:
newArr[action.key] = filterIdx !== -1
? [...newArr[action.key].slice(0, filterIdx), ...newArr[action.key].slice(filterIdx+1)]
: [...newArr[action.key], action.value[0]]);
BTW, you don’t have to copy newArr again, as it already is a copy of filters. You can replace:
filters: {
...newArr,
},
by just:
filters: newArr,