Reputation: 125
I need to increment quantity of item in cart if item already exists in the state array. In the reducer I got it to work but it needs to be immutable. Because of this, my component doesnt update properly.
This is the code for my reducer:
import { ADD_TO_CART, REMOVE_FROM_CART } from '../actions/types';
const initialState = [];
//Cannot mutate array in reducer
export default function(state = initialState, action){
const { type, payload } = action;
switch(type){
case ADD_TO_CART:
const newState = [...state]
for(var i = 0; i < newState.length; i++){
if(newState[i].item.uid === payload.item.uid){
newState[i].item.qty ++;
return [...newState];
}
}
return [...state, payload];
case REMOVE_FROM_CART:
for(var j = 0; j < state.length; j++){
if(state[j].item.uid === payload.uid){
state[j].item.qty = 1;
}
}
return state.filter(cartItem => cartItem.item.uid !== payload.uid);
default:
return state;
}
}
I need to increment qty if item is already in the array.
Upvotes: 1
Views: 1706
Reputation: 202686
The issue I see is with newState[i].item.qty++;
, that although you shallowly copied the array, the elements in the array still represent those of the previous state, so post incrementing it mutates the object.
To resolve this issue you should also copy each item into a new object, then update the new object reference.
The following also include a minor optimization to iterate the data once versus twice, by checking for the matching item ID as it copying the state into a new array.
let itemExists = false;
const newState = state.map(item => {
const newItem = { ...item };
if (newItem.item.uid === payload.item.uid) {
itemExists = true;
newItem.item.qty = item.qty + 1;
}
return newItem;
});
if (!itemExists) newState.push(payload);
return newState;
EDIT: Alternative method
const itemIndex = state.findIndex(item => item.item.id === payload.item.id);
if (itemIndex !== -1) {
return state.map((item, i) => ({
...item,
item: {
...item.item,
qty: item.item.qty + (itemIndex === i ? 1 : 0),
}
}));
} else {
return [...state, payload];
}
Upvotes: 1