我是React的初学者。面对一个问题不知道为什么。 使一组产品进入反应状态。
当用户单击按钮(通过子组件)时,我正在从状态克隆当前产品数组,然后对其进行修改,但是状态正在更新而不调用setState。 帮助真的很感激。我想知道为什么它会像这样。
这是App组件文件:
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
id: 1,
img: 'http://placehold.it/460x250/e67e22/ffffff&text=HTML5',
title: 'Laptop',
quantity: 1,
price: 250,
},
],
cart_products: [],
total_price: 0,
total_product: 0,
};
}
addProductToCart = (id) => {
let cartProducts = [];
// Trying to clone first
let productCopy = [...this.state.products];
// Find specific product
let newProduct = productCopy.find((item) => {
return item.id === id;
});
// Now into new product I want to add some extra property
newProduct['originalPrice'] = newProduct.price;
// Here I want some other code.
cartProducts.push(newProduct);
this.setState({
cart_products: cartProducts
});
}
render() {
return (
<div className="container-fluid">
<div className="container">
<h1 className="text-center">React.js Example </h1>
</div>
<div>
<div className="col-sm-6">
<Cart products={this.state.cart_products} totalPrice={this.state.total_price} totalProduct={this.state.total_product} />
</div>
<div className="col-sm-6">
<Products products={this.state.products} onClicked={this.addProductToCart} />
</div>
</div>
</div>
);
}
}
问题是“产品”阵列进入状态自动更新。这是React Chrome Extension的图片
应用程序的想法只是简单的购物车系统。当用户单击添加产品按钮时,我想将特定产品添加到购物车中。但是我被困在如何解决这个问题上。
答案 0 :(得分:1)
我可以在行
看到一些问题let productCopy = [...this.state.products];
只需将行替换为
let productCopy = JSON.parse(JSON.stringify([...this.state.products]))
为什么需要它?
这就是传播运算符在复制复杂变量时的工作方式。 这里是reference,其中
注意:复制文件时,传播语法有效地深入了一层 数组。因此,它可能不适合复制多维 数组如以下示例所示(与 Object.assign()和传播语法)。
答案 1 :(得分:1)
您可以使用传播对象语法来创建新属性,而不会在以下状态下更改原始对象:
addProductToCart = (id) => {
const { products, cart_products } = this.state;
// Find the relevant product
let relevantProduct = products.find((item) => {
return item.id === id;
});
// Now into new product I want to add some extra property
const newProduct= {
...relevantProduct,
originalPrice: relevantProduct.price
};
this.setState({
cart_products: [...cart_products, newProduct]
});
}
运行示例:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
products: [
{
id: 1,
img: 'http://placehold.it/460x250/e67e22/ffffff&text=HTML5',
title: 'Laptop',
quantity: 1,
price: 250,
},
],
cart_products: [],
total_price: 0,
total_product: 0,
};
}
addProductToCart = (id) => {
const { products, cart_products } = this.state;
// Find the relevant product
let relevantProduct = products.find((item) => {
return item.id === id;
});
// Now into new product I want to add some extra property
const newProduct = {
...relevantProduct,
originalPrice: relevantProduct.price
};
this.setState({
cart_products: [...cart_products, newProduct]
});
}
render() {
const { products, cart_products } = this.state;
return (
<div>
<div>Cart</div>
{
cart_products.map((product, index) => <div key={index}>{product.title}</div>)
}
<hr />
<div>Product list</div>
{
products.map((product, index) => (
<div>
<div key={index}>{product.title}</div>
<button onClick={() => this.addProductToCart(product.id)}>Add</button>
</div>)
)
}
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
答案 2 :(得分:0)
在JS对象中通过引用传递。
我不确定您是否已经知道这个事实,但是在JS中,我猜几乎所有编程语言的对象都是通过引用传递的。在您的代码中的以下行:
// Trying to clone first
let productCopy = [...this.state.products];
...当然,您正在创建一个新数组productCopy
,但是即使是新数组,也将具有与先前数组this.state.products
相同的对象,而不是这些对象的某些克隆正如您所期望的。
您可以编写自己的代码来深度克隆对象和数组。或者,您可以使用一些非常好的JS库,例如lodash,如下所示:
var arr = [{a:1, b:2}, {c:3, d:4}]
var newArr = _.cloneDeep(arr);
newArr[0].e = 5;
console.log(arr[0]);
console.log(newArr[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>