反应如何处理添加到购物车

React how to handle add to Cart

所以我有一个电子商务网页,但出于某种原因,在第一次将商品添加到购物车后,它开始使购物车中的单位价值翻倍,同时我的 Toasts 也翻了一番。我想知道我在这里做错了什么。 cartItem 的初始状态为 0。任何帮助将不胜感激。

这是我正在使用的东西:

cartItem 对象示例:

[{
description: "...."
featured: false
id: "6u7pLcaGApuGtiNAf6zLMf"
image: ["//images.ctfassets.net/f1r553pes4gs/17rq7BQ76Q7ouq…010636019e9b3cbc3a10/il_794xN.2378509691_kaep.jpg"]
inCart: false
ingredients: (2) ["Distilled Water", "99.99% Fine Silver Rods"]
price: 20
productName: "Quintessence Colloidal Silver (4 fl oz)"
slug: "quintessence-colloidal-silver-4oz"
units: 9
}]

代码的简化版本:

export class StoreProvider extends Component {
  //Initialized State ready for API Data
  state = {
    products: [],
    featuredProducts: [],
    sortedProducts: [],
    price: 0,
    maxPrice: 0,
    minPrice: 0,
    units: 0,

    loading: true,
    //FIXME CART
    cartItem: []
  }

 handleAddToCart = (e, products) => {
    this.setState(state => {
      const cartItem = state.cartItem;
      let productsAlreadyInCart = false;
      cartItem.forEach(cp => {
        if (cp.id === products.id) {
//Have tried ++
          cp.units+= 1;
          productsAlreadyInCart = true;
          this.successfullCartToast()
        }
      });

      if (!productsAlreadyInCart) {
        cartItem.push({ ...products});
      }
      localStorage.setItem('cartItem', JSON.stringify(cartItem));
      return { cartItem: cartItem };
    });
  }
}

//Button is in seperate component
 <button
    className="btn-primary rounded col-sm-6 col-lg-12 align-self-center ml-1 p-2"
    onClick={(e) => handleAddToCart(e, product)}>
     + Cart
 </button>

所以,cartItem 是一个对象,看起来像:

[{'id': 123, 'units': 2}, {'id': 345, 'units': 1}, ...] ?

要尝试的一件事是制作对象的深拷贝,这样它在更新时不会改变:

handleAddToCart = (e, products) => {
    this.setState(state => {
      //const cartItem = state.cartItem;
      // make deep copy, so state doesn't change while manipulating:
      const cartItem = JSON.parse(JSON.stringify( state.cartItem ));
      let productsAlreadyInCart = false;
      cartItem.forEach(cp => {
        if (cp.id === products.id) {
          //Have tried ++
          cp.units += 1;
          productsAlreadyInCart = true;
          this.successfullCartToast()
        }
      });

      if (!productsAlreadyInCart) {
        cartItem.push({ ...products});
      }
      localStorage.setItem('cartItem', JSON.stringify(cartItem));
      return { cartItem: cartItem };
    });
  }
}

问题

您正在改变现有状态 烘烤您检查的每个购物车项目。

解决方案

如果商品已包含,则首先搜索购物车数组。如果它已经包含,则只需映射购物车并更新适当的索引,否则,附加到浅拷贝的购物车项目数组。

此外,setState 应该是一个纯函数,所以不要像设置 localStorage inside 这样的副作用 setState 函数更新,而是使用 setState 回调,或者最好使用 componentDidUpdate 生命周期函数。或者您可以将 localStorage 设置为与更新状态相同的值。

handleAddToCart = (e, products) => {
  const itemFoundIndex = this.state.cartItem.findIndex(
    cp => cp.id === products.id
  );

  let cartItem;

  if (itemFoundIndex !== -1) {
    this.successfullCartToast();
    // map cart item array and update item at found index
    cartItem = this.state.cartItem.map((item, i) =>
      i === itemFoundIndex ? { ...item, units: item.units + 1 } : item
    );
  } else {
    // shallow copy into new array, append new item
    cartItem = [...this.state.cartItem, products];
  }

  localStorage.setItem("cartItem", JSON.stringify(cartItem));
  this.setState({ cartItem });
};