When i click this button:
const addToCart = () => {
dispatch({
type: "ADD_TO_CART",
item:{
id:id,
name: name,
image: image,
price: price,
score: score,
releaseDate: releaseDate,
amount: amount // this is defaulted as 1
}
})
}
It sends it to my reducer class that stores data, im trying to edit it so it will only have a single instance of a specific item and only increase the amount
case 'ADD_TO_CART':
for (let x of state.cart){
// this should get fired if the object is found and increase amount by specified
if (x.id === action.item.id){
let newCart1 = [...state.cart];
newCart1[x] = { ...newCart1[x], amount: x.amount = action.item.amount }
return {...state, cart: [newCart1]}
}
}
return { ...state, cart: [...state.cart, action.item], };
// this should get fired if it is not found and add the whole object
There are two issues.
If I add an initial item it works (initial object) if I add a second of the same item it will increase amount to 3 instead of 2
On top of that it adds a "Object object" with amount 3 which I don't know what this is or how it is included given the array is of length 1 (second object)
CodePudding user response:
This question relates more towards an finding and resolving a bug in the code. Below is an attempt to do so.
- This line
for (let x of state.cart)
indicates thatx
is an element of thestate.cart
(an array) - The next line:
if (x.id === action.item.id)
reinforces thatx
is not just an element, but it is probably anobject
which has a propid
. - Next,
let newCart1 = [...state.cart];
indicates thatnewCart1
is a shallow-copy of the object-arraystate.cart
- And here (in the next assignment) lies the problem (I think):
newCart1[x] = { ...newCart1[x].....
<---x
is an object and it is being used as an index to accessnewCart1
. May be one needs to find the index of the matchedid
and use that here (instead of[x]
)?
This answer may need to be updated based on further response/clarification from OP.
Observation
Rather than loop through the cart
array, if it may be guaranteed that action.item.id
will only match one item in the cart
array, then why not just do this:
case 'ADD_TO_CART':
const newCart1 = [...state.cart];
const tgtIdx = newCart1.findIndex(({ id }) => id === action.item.id);
if (tgtIdx >= 0 && tgtIdx < newCart1.length) {
newCart1[tgtIdx] = {
...state[tgtIdx],
amount: state[tgtIdx].amount action.item.amount
};
return { ...state, cart: [...newCart1]};
};
return { ...state, cart: [...state.cart, action.item] };
Note: The existing for...of
loop will also only target the first occurrence as the moment it finds a match, it executes a return
from within the loop.
CodePudding user response:
case 'ADD_TO_CART':
const newCart1 = [...state.cart];
const tgtIdx = newCart1.findIndex(({ id }) => id === action.item.id);
if (tgtIdx >= 0 && tgtIdx < newCart1.length) {
newCart1[tgtIdx] = { ...newCart1[tgtIdx], amount: newCart1[tgtIdx].amount action.item.amount}
return { ...state, cart: [...newCart1]};
};
return { ...state, cart: [...state.cart, action.item] };