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,