Home > database >  JS editing array - result amount is incorrect and stray object
JS editing array - result amount is incorrect and stray object

Time:04-12

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.

  1. 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

  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)

enter image description here

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 that x is an element of the state.cart (an array)
  • The next line: if (x.id === action.item.id) reinforces that x is not just an element, but it is probably an object which has a prop id.
  • Next, let newCart1 = [...state.cart]; indicates that newCart1 is a shallow-copy of the object-array state.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 access newCart1. May be one needs to find the index of the matched id 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] };
  • Related