Reputation: 1274
I'm creating a simple Point of sale
system and in my Cart reducer
.
I need to check if the object
is already in the Cart Array
then increment the quantity. And if the Object
does not exist push it into the Cart Array
The code is working as expected. But is there a better workaround ?
Cart Reducer
export const cartReducer = (state: IState, action: Actions) => {
const { uid } = action.payload
switch (action.type) {
case 'ADD_TO_CART': {
const cart_item = state.cart.filter(item => item.uid === uid)
if (cart_item.length > 0) {
return {
...state,
cart: state.cart.map(item => item.uid === uid ? { ...item, quantity: item.quantity + 1 } : item)
}
}
return {
...state,
cart: [...state.cart, action.payload]
}
}
}
}
Upvotes: 1
Views: 1209
Reputation: 4330
Instead of looping over all items twice (ones to filter and once to map) you can simply use findIndex
.
The benefit of findIndex
over filter
: iteration will stop once the condition is fulfilled and you'll get its index, unlike filter where the loop iterates over all the elements in the array.
If your array has fewer elements, your solution is fine, but findIndex
will give better performance in the case of long arrays.
switch (action.type) {
case 'ADD_TO_CART': {
const cartItemIndex = state.cart.findIndex(item => item.uid === uid)
const updatedCart = [...state.cart]
if (cartItemIndex > -1) {
updatedCart[cartItemIndex] = { ...updatedCart[cartItemIndex], quantity: item.quantity + 1 }
}
else {
updatedCart.push(action.payload)
}
return {
...state,
cart: updatedCart
}
}
}
Upvotes: 2
Reputation: 370779
That looks mostly reasonable to me, but you could make a slight improvement by
cart
ahead of time instead of returning twicesome
instead of filter
case 'ADD_TO_CART': {
const exists = state.cart.some(item => item.uid === uid);
const cart = exists
? state.cart.map(item => item.uid === uid ? { ...item, quantity: item.quantity + 1 } : item)
: [...state.cart, action.payload];
return {
...state,
cart
};
}
Upvotes: 2