反应如何处理添加到购物车
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 });
};
所以我有一个电子商务网页,但出于某种原因,在第一次将商品添加到购物车后,它开始使购物车中的单位价值翻倍,同时我的 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 });
};