0

I wants to prevent addition of duplicate items to cart. I have tried the code below but it's working only for single item, when there are multiple items in the cart the duplicate items are allowed to add in to the cart. Here is my code

addToCart = (id) => {
    let item = this.getItem(id);
    if ([...this.state.cart]) {
      [...this.state.cart].map((i) => {
        if (i.product_name == item.product_name) {
          alert("Item is already in cart");
        } else {
          this.setState((this.state.cart = [...this.state.cart, item]));
        }
      });
    } else {
      this.setState((this.state.cart = [...this.state.cart, item]));
    }
    console.log(this.state.cart);
  };

4 Answers4

1

You need to use map only to check if the item already exists, and then either add it or alert that the item is repeated.

One way of doing it would be like this:

existing = [...this.state.cart].map((i) => {
    if (i.product_name == item.product_name) {
        return i;
    }
});
if (existing) {
    alert("Item is already in cart");
} else {
    this.setState((this.state.cart = [...this.state.cart, item]));
}

Explanation

map function executes the code for each of the items in the collection, which means the moment it finds an item in the cart different from the item selected, it will add the item selected.

So let's say your cart has [apple, orange] and you want to add apple again. When the map code executes it first looks like this:

if ("apple" == "apple") {
    alert("Item is already in cart");
} else {
    this.setState((this.state.cart = [...this.state.cart, apple]));
}

It doesn't add the item because it already exists... but then it executes a second time, and it looks like this:

if ("orange" == "apple") {
    alert("Item is already in cart");
} else {
    this.setState((this.state.cart = [...this.state.cart, apple]));
}

It gets added because the second item is different.

What the new code does is that it returns a value only if the item exists and, after looping throuhght all the items in the cart, it checks that value and adds the item if it is nothing.

Josh Part
  • 2,154
  • 12
  • 15
1

An item should be added to the cart, if the latter doesn't contain it already.
To check if an Array contains an object, that fulfills a certain condition use the some method, as said by @Isaac Batista.

On the other hand, when you want to update state, by using it's previous value, you should use the callback argument of setState.
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

this.setState((state)=>{
    // if cart already contains item
    if(state.cart.some(itm=>itm.product_name == item.product_name)) {
        return {}; // do not update state
    } else {
        return {cart: state.cart.concat(item)}; // add item to cart
    }
}
Nice Books
  • 1,675
  • 2
  • 17
  • 21
0

Here is a functional exemple, but note some points:

  1. You are mutating state, and you should not do it, as it is explained here. So, you should just call setState passing the new value via argument, like this: this.setState(newValue).

  2. A map is used to create a new array, the correct function to find out if some element passes a rule is some. This will allow you to check if some product inside cart is the clicked product.

    // quick example
    [1,2,3,4].some(number => number === 2) // true
    [1,2,3,4].some(number => number === 5) // false
    
  3. Finally, i would do something like this

    const { cart } = this.state;
    
    const product = this.getItem(id);
    
    // returns true if there is any product with the same id
    const isProductInCart = cart.some((item) => item.id === product.id);
    
    if (isProductInCart) {
      alert("Product already in cart");
    } else {
      this.setState({
        cart: [...cart, product]
      });
    }
    
0

You can use filter method to check whether the item is already available or not. With this you can also avoid the nested if condition also.

addToCart = (id) => {
    let item = this.getItem(id);
    let checkCart = [...this.state.cart].filter((i) => {
        return i.product_name == item.product_name;
    });
    if (checkCart.length !== 0) {
        alert("Item is already in cart");
    } else {
        this.setState((this.state.cart = [...this.state.cart, item]));
    }
    console.log(this.state.cart);
  };
Sujith Sandeep
  • 1,185
  • 6
  • 20