[英]why state updating itself? Without calling setState
我是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的图片
应用程序的想法只是简单的购物车系统。 当用户单击添加产品按钮时,我想将特定产品添加到购物车中。 但是我被困在如何解决这个问题上。
我可以在网上看到一些问题
let productCopy = [...this.state.products];
只需将其替换为
let productCopy = JSON.parse(JSON.stringify([...this.state.products]))
为什么需要它?
这就是传播运算符在复制复杂变量时的工作方式。 这里是参考 ,说,
注意 :传播语法在复制数组时有效地深入了一层。 因此,如下面的示例所示,它可能不适合复制多维数组(与Object.assign()和spread语法相同)。
您可以使用传播对象语法来创建新属性,而无需更改状态中的原始对象:
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>
在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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.