Reputation: 33
I want to change the quantity value of a certain object in my cart array. Each object in cart array have (id, item_id, quantity, name, price).
But when my map function find that specific cart, instead of changing only quantity of that object, it replaces the whole object with the quantity value.
Please tell me what I am doing wrong.
action.payload
{
id: "a6e1868f-e1bc-4180-abc6-328fdd8e922f",
quantity: 7
}
state.cart.map(cartItem => cartItem.id === action.payload.id ? cartItem.quantity = action.payload.quantity : cartItem)
Upvotes: 0
Views: 3732
Reputation: 28654
state.cart.map(cartItem => cartItem.id === action.payload.id ? cartItem.quantity = action.payload.quantity : cartItem)
when you return some element say x
at some index from callback of map
, the corresponding element which was being mapped is replaced with this x
, that is how map works.
You are returning this:
cartItem.quantity = action.payload.quantity // btw don't mutate state items like this
let x;
console.log(x=9); // logs 9
console.log([1,2].map(y=>y=9)) // logs [9,9]
You want immutable approach since you are iterating state items:
let newVal=99;
let res = [{
a: 1,
b: 2
}].map(cartItem =>
cartItem.a === 1 ? {
...cartItem,
quantity: newVal
} : cartItem
);
console.log(res)
Upvotes: 1
Reputation: 5084
You can use spread operator to copy all the properties of item
object, and then, you can replace quantity with action.payload.quantity
let cartItem = {
id: "a6e1868f-e1bc-4180-abc6-328fdd8e922f",
quantity: 5
}
let action = {
payload: {
id: "a6e1868f-e1bc-4180-abc6-328fdd8e922f",
quantity: 7
}
}
let cart = [cartItem]
let result = cart.map(item=>{
if(item.id === action.payload.id){
return {...item, quantity: action.payload.quantity};
} else{
return item;
}
})
console.log(result)
Upvotes: 1
Reputation: 717
Lets look at how Map function works:
Map function gets an Array .. goes through it while using function you define to map every element of 1st array to 2nd (new array).
You return just a number if id's are same so new element of new array will be just number:
|are id's same| ? YEP return number : NOPE return <object>
It should be:
|are id's same| ? YEP return <object> : NOPE return <object>
Fix of original code:
state.cart.map(cartItem => cartItem.id === action.payload.id ? { ...cartItem, quantity: action.payload.quantity} : cartItem)
Upvotes: 0
Reputation: 301
There are some problems in
previous: state.cart.map(cartItem => cartItem.id === action.payload.id ? cartItem.quantity = action.payload.quantity : cartItem)
you can check this:
correct: state.cart.map(cartItem => cartItem.id === action.payload.id ? {...cartItem,quantity:action.payload.quantity} : cartItem)
Upvotes: 0
Reputation: 3130
The main issue is that you are using arrow functions "without a body" (in other words, without using {}
). This means that your arrow function is implicitly returning the resulting value of any expression succeeding the =>
symbol. In this case it will be action.payload.quantity
or cartItem
depending if the item ID is matched or not.
Additionally, I assume that you are using the result of the map
operation (a new array with the returned items) to update your state.
If you are using Redux Toolkit or something else to ensure immutability (I assume you do because your code however is not respecting immutability as inner items are being returned as references and not as new values), you could replace your map
function with a for
loop or other loop structure (like Array.prototype.find
) that allows you to interrupt the loop after finding the item you was looking for.
If you want to fix your code and leave it as it is (not recommended), you can do as follows:
state.cart.map(cartItem => {
if (cartItem.id === action.payload.id) {
cartItem.quantity = action.payload.quantity;
}
return cartItem;
});
Upvotes: 0