RogerFedFan
RogerFedFan

Reputation: 566

Change Value of Object Once Added To Array

My state looks like so:

items: [
  { id: 1, name: 'banana', price: 100, quantity: 1 },
  { id: 2, name: 'apple', price: 200, quantity: 1 },
  { id: 3, name: 'blueberry', price: 300, quantity: 1 }
]

cart: []

I have a function where I push the item to the cart:

addItem = item => {
  const { cart, total, itemQuantity } = this.state
  const { price, id } = item
  const i = cart.indexOf(item)

  if (!cart.some(x => x.id === id)) {
    this.setState({
      cart: [...cart, { ...item, quantity: itemQuantity }],
      total: total + (price * itemQuantity)
    })
  }
}

I'm checking to see if the item exists before adding it to avoid duplicates. What I want to happen is if the item is already added to the cart, I want to find that object and change its quantity value.

Is this possible to do?

Upvotes: 0

Views: 79

Answers (4)

deowk
deowk

Reputation: 4318

You could do something like this:

addItem = item => {
  const { cart, total, itemQuantity } = this.state
  const { price, id } = item
  const index = cart.findIndex(x => x.id === id);
  let quantity = itemQuantity;

  const newCart = index === -1 
     ? [...cart, {...item, quantity }] 
     : cart.map((it, i) => {
           if (i === index) {
             quantity = it.quantity + quantity;
             return { ...it, quantity }
           } else return it
       });

  this.setState({
    cart: newCart,
    total: total + (price * quantity)
  });

}

Upvotes: 0

RogerFedFan
RogerFedFan

Reputation: 566

I had to check to see whether the item was added to the cart before pushing a new object with that item.

I then had to find the index of that item in the cart and update its quantity.

addItem = item => {
  const { cart, total, itemQuantity } = this.state
  const { price, id } = item
  const i = cart.findIndex(x => x.id === id)

  if (!cart.some(x => x.id === id)) {
    this.setState({
      cart: [
        ...cart,
        { ...item, quantity: itemQuantity }
      ]
    })
  } else {
    this.setState({
      cart: [
        ...cart.slice(0, i),
        { ...cart[i], quantity: cart[i].quantity + itemQuantity },
        ...cart.slice(i + 1)
      ]
    })
  }

  this.setState({
    total: total + (price * itemQuantity)
  })
}

Upvotes: 0

nowy
nowy

Reputation: 394

Yes, just leverage the i const that you've already defined!

addItem = item => {
  const { cart, total, itemQuantity } = this.state
  const { price, id } = item
  const i = cart.indexOf(item)
  const newCart = [...cart]
  const newTotal = total + (price * itemQuantity)

  if (i !== -1) {
    const newItem =  { ...item, quantity: itemQuantity + 1 }

    newCart[i] = newItem

    this.setState({
      cart: newCart,
      total: newTotal,
    })

    return
  }

  newCart.push({ ...item, quantity: itemQuantity })

  this.setState({
    cart: newCart,
    total: newTotal,
  })
}

Note, it was unclear how you wanted the total functionality to work, so I've left that as it is. This, however will update the item you're looking for.

Upvotes: 0

Tom O.
Tom O.

Reputation: 5941

I think the solution below would work for you without having to update your design much. You really just have to call Array.prototype method reduce on an array of items you wish to add to the cart. Make sure to pass your cart's current state as the initial value to reduce (pass it as the second argument). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

With some simple logic, you could just check to see if the item id already exists in the cart (which is just an object literal keyed by item id). If it doesn't, add the object and set the quantity property to 1 - if it does, just increment the quantity property by 1.

Hopefully the example below is clear and can help you out:

//an array of items we want to add to the cart
var items = [{
    id: 1,
    name: 'banana',
    price: 100,
    quantity: 1
  },
  {
    id: 2,
    name: 'apple',
    price: 200,
    quantity: 1
  },
  {
    id: 3,
    name: 'blueberry',
    price: 300,
    quantity: 1
  }
];

//function utilizing reduce to update our cart object
function updateCart(cartToUpdate, itemsToAdd) {
  itemsToAdd.reduce(function(cart, cartItem) {
    if (!cart[cartItem.id]) {
      cart[cartItem.id] = {
        name: cartItem.name,
        price: cartItem.price,
        quantity: 1
      }
    } else {
      cart[cartItem.id].quantity++;
    }

    return cart;
  }, cart);
}

//implement cart as an object keyed on item id
var cart = {
  1: {
    name: 'banana',
    price: 100,
    quantity: 1
  }
};
//i manually added a single banana to the cart so we can show that our update function works properly

console.log('Cart before update:');
console.log(cart);

updateCart(cart, items);

console.log('Cart after update:');
console.log(cart);

//from here it's really easy to see how many of each item we have in the cart:
Object.keys(cart).forEach(function(key) {
  console.log(`The customer has ${cart[key].quantity} ${cart[key].name}(s) in their cart`)
});
//

Upvotes: 1

Related Questions