繁体   English   中英

为什么要状态更新本身? 不调用setState

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM