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

Javascript 反应如何处理添加到购物车,javascript,reactjs,e-commerce,shopping-cart,Javascript,Reactjs,E Commerce,Shopping Cart,所以我有一个电子商务网页,但出于某种原因,在第一次向购物车添加物品后,它开始使购物车中的单位价值翻倍,并使我的祝酒词翻倍。我想知道我在这里做错了什么。cartItem的初始状态为0。任何帮助都将不胜感激 以下是我的工作内容: cartItem对象的示例: [{ description: "...." featured: false id: "6u7pLcaGApuGtiNAf6zLMf" image: ["//images.ctfassets.n

所以我有一个电子商务网页,但出于某种原因,在第一次向购物车添加物品后,它开始使购物车中的单位价值翻倍,并使我的祝酒词翻倍。我想知道我在这里做错了什么。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>

导出类StoreProvider扩展组件{
//API数据的初始化状态就绪
状态={
产品:[],
特色产品:[],
分类产品:[],
价格:0,,
maxPrice:0,
价格:0,
单位:0,,
加载:对,
//修理车
项目:[]
}
HandleadToCart=(e,产品)=>{
this.setState(state=>{
const cartItem=state.cartItem;
让ProductsReadyInCart=false;
cartItem.forEach(cp=>{
if(cp.id==products.id){
//试过++
cp.units+=1;
ProductsReadyInCart=true;
这个。successfullCartToast()
}
});
如果(!ProductsReadyInCart){
推送({…产品});
}
setItem('cartItem',JSON.stringify(cartItem));
返回{cartItem:cartItem};
});
}
}
//按钮位于单独的组件中
手持式(e,产品)}>
+推车

因此,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
应该是一个纯函数,所以不要在
setState
函数更新中设置localStorage这样的副作用,而是使用
setState
回调,或者最好使用
componentdiddupdate
生命周期函数。或者,您可以使用更新状态时使用的相同值设置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 });
};

你能分享更多你的代码吗?可能是完整的组件,你可以在其中初始化你的状态。我可以添加更多,但都在一个上下文中,所以这个组件中有250多行