【问题标题】:How to stop child component function running again after parent state changed?父状态改变后如何停止子组件功能再次运行?
【发布时间】:2019-05-21 05:24:31
【问题描述】:

我有两个组件:App(parent) 和 AddToCart(child)。在子组件中,我将孩子的整个状态添加到 localStorage;然后我在将东西添加到 localStorage 时从孩子的父级调用一个函数,该函数检查 localStorage 项目并更改父组件的状态。但是,问题是在父状态更改后,它调用了子函数,该函数将相同的东西两次添加到 localStorage。

我尝试将本地存储数据存储在父组件的 props 中,但它没有将 prop 值传递给其他子组件。

这是 AddToCart 组件(子)代码:

import React, { Component } from "react";

let cartItems = [];

export default class AddToCart extends Component {
  constructor(props) {
    super(props);
    this.state = {
      one: ""
    };
  }

  updateCart = () => {
    this.setState(
      {
        one: "some value"
      },
      () => {
        this.props.checkCart();
      }
    );
  };

  componentDidUpdate() {
    this.populateStorage();
    console.log("function is being called twice");
  }

  populateStorage = () => {
    cartItems.push(this.state);
    localStorage.setItem("cart", JSON.stringify(cartItems));
  };

  render() {
    return (
      <React.Fragment>
        <button className="btn btn--white" onClick={this.updateCart}>
           Add to cart
        </button>
      </React.Fragment>
    );
  }
}

这里是 App 组件(父)代码:


import React, { Component } from "react";

import Header from "./components/layouts/Header";
import AddToCart from "./components/AddToCart";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { cartCount: 0 };
  }

  handleCartCount = cart => {
    let count = cart.length;
    this.setState({ cartCount: count });
  };

  componentDidMount() {
    this.checkCart();
  }

  checkCart = () => {
    if (localStorage.getItem("cart")) {
      let cartStorage = JSON.parse(localStorage.getItem("cart"));
      return this.handleCartCount(cartStorage);
    } else {
      console.log("Cart is empty!");
    }
  };

  render() {
    return (
      <div className="App">
        <Header cartCount={this.state.cartCount} />
        <AddToCart checkCart={this.checkCart} />
      </div>
    );
  }
}

export default App;

有没有办法阻止子组件再次更新?谢谢。

【问题讨论】:

  • 您看到的是一个理想的行为 componentDidUpdate 不是调用populateStorage 的正确位置。它必须在 updateCart 的回调中调用。
  • @VishalSharma 的评论是正确的,但我应该把我的两分钱放进去,我应该提到,当你使用 componentDidUpdate 时,你几乎总是需要检查你的道具或状态是否已经改变。您可以阅读有关无限循环和正确用法的文档reactjs.org/docs/react-component.html#componentdidupdate
  • 您需要在componentDidUpdate上添加条件。这不是使用componentDidUpdate的正确方法(检查值是否已更改)。如果您不想使用相同的道具渲染组件。然后改用 shouldComponentUpdate(reactjs.org/docs/react-component.html#shouldcomponentupdate)。
  • @VishalSharma 成功了!我已将 populateStorage 移至 updateCart 方法并摆脱了 componentDidUpdate()
  • @DebadiptiPatra 我了解它的工作原理,但您可能并不总是需要它。如果你需要它,那么 Shubham 所说的就是要做的。

标签: javascript reactjs


【解决方案1】:

首先,您不需要componentDidUpdate()。这将导致您在组件首次呈现后立即保存项目。

在您从updateCart() 设置状态后,重新设计您的组件以在回调中使用 this.populateStorage()

import React, { Component } from "react";

let cartItems = [];

Here's the sandbox for reference: https://codesandbox.io/s/black-sun-i4omf

    export default class AddToCart extends Component {
      constructor(props) {
        super(props);
        this.state = {
          one: ""
        };
      }

      updateCart = () => {
        this.setState(
          {
            one: "some value"
          },
          () => {
            this.populateStorage();
          }
        );
      };


      populateStorage = () => {
        cartItems.push(this.state);
        console.log(cartItems);
        localStorage.setItem("cart", JSON.stringify(cartItems));
      };

      render() {
        return (
          <React.Fragment>
            <button className="btn btn--white" onClick={this.updateCart}>
              Add to cart
            </button>
          </React.Fragment>
        );
      }
    }

【讨论】:

  • 这与我在评论中提到的相同。
  • 是的.. 我摆脱了 componentDidUpdate() 并将 populateStorage() 移动到 updateCart() 回调。它奏效了!谢谢!
猜你喜欢
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 2016-12-23
  • 2021-03-23
  • 2019-09-21
  • 1970-01-01
  • 2023-03-19
  • 2021-12-22
相关资源
最近更新 更多