【问题标题】:why state updating itself? Without calling setState为什么状态更新自己?不调用 setState
【发布时间】:2019-01-05 06:30:22
【问题描述】:

我是 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 扩展的图片

方法调用之前

方法调用后:

应用程序的想法只是简单的购物车系统。当用户单击添加产品按钮时,我想将特定产品添加到购物车中。但我不知道如何解决这个问题。

【问题讨论】:

  • 在你使用onClick事件的地方发布你的渲染代码
  • 我编辑了添加渲染方法的问题。希望能帮到你

标签: javascript reactjs ecmascript-6


【解决方案1】:

我可以在一行看到一些问题

let productCopy = [...this.state.products];

只需将行替换为,

let productCopy = JSON.parse(JSON.stringify([...this.state.products]))

为什么需要它?

这就是扩展运算符在复制复杂变量时的工作方式。 这是reference,上面写着,

注意:传播语法在复制一个 大批。因此,它可能不适合复制多维 如下例所示的数组(与 Object.assign() 和传播语法)。

【讨论】:

  • 你的想法不错,但我的意思是根据标准它不是有效代码
  • 啊,我有点困惑..为什么你认为它无效?我的意思是,我们需要删除复杂对象的引用,这样它就不会影响源
  • 代码变重,将其传入 JSON 并再次转换为对象或数组是无效的。
  • JSON.parse(JSON.stringify()) 在删除复杂 javascript 对象的引用时,它的效果最好。其他 javascript 选项在处理多级复杂对象时失败,因为它不处理嵌套引用
【解决方案2】:

在 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]);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 是的,我知道,但我想要解决方案
【解决方案3】:

您可以使用扩展对象语法来创建新属性,而无需改变状态中的原始对象:

  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>

【讨论】:

  • 确定没问题,我已经添加了一个使用您的代码的简单示例以防万一
猜你喜欢
  • 2020-03-13
  • 2020-10-04
  • 2018-12-08
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多