Reputation: 566
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
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
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
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
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