【问题标题】:Maximum Depth exceeded in my CartIcon component我的 CartIcon 组件超出了最大深度
【发布时间】:2020-10-18 00:30:33
【问题描述】:

我想在用户添加新商品时使用购物车图标动态显示购物车中的商品数量。但我收到“最大深度超出错误”。 我正在使用 useEffect 通过将状态设置为项目并将项目作为依赖项数组放在购物车图标组件中来监听购物车中项目的变化。 我这样做是因为 window.addEventListener('storage', cartTotal) 不工作。

这是我的购物车图标组件

const CartIcon = ({ fill, className }) => {
  const [items, setItems] = useState();

  useEffect(() => {
    setItems(getCart());
    cartTotal();
  }, [items]);

  return (
    <div className="cart-icon">
      <svg
        width="2.5em"
        height="2.5em"
        viewBox="0 0 16 16"
        className="bi bi-bag cart"
        fill={fill}
        xmlns="http://www.w3.org/2000/svg"
      >
        <path
          fillRule="evenodd"
          d="M8 1a2.5 2.5 0 0 0-2.5 2.5V4h5v-.5A2.5 2.5 0 0 0 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5v9a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5H2z"
        />
      </svg>
      <span className={className}>{cartTotal()}</span>
    </div>
  );
};

export default CartIcon;

getCart 函数用于从localStorage 中获取购物车中的商品,而cartTotal 是获取购物车中商品数量的函数。这是他们的代码。

//Get the items in the cart
export const getCart = () => {
  if (typeof window !== "undefined") {
    if (localStorage.getItem("cart")) {
      return JSON.parse(localStorage.getItem("cart"));
    }
  }
  return [];
};


//Get total number of items in the cart
export const cartTotal = () => {
  if (typeof window !== "undefined") {
    if (localStorage.getItem("cart")) {
      return JSON.parse(localStorage.getItem("cart")).length;
    }
  }
  return 0;
};

***更新:所以我应该包括显示 CartIcon 组件的导航栏,该导航栏仅在整个应用程序中安装一次(除了 /signin 和 /signout 路径)。所以设置一个空数组意味着 useEffect 几乎不会在整个应用程序中再次运行。这样, CartIcon 中的项目数在我刷新之前不会改变。 “添加到购物车”按钮也在不同的组件中。 LocalStorage 是 CartIcon 知道购物车中有多少商品的唯一方法。

【问题讨论】:

  • 你确定你的代码中没有无限循环吗?
  • 这类错误只发生在无限循环的情况下,或者在每次渲染时执行该函数,然后重新渲染组件。
  • 是的,循环是因为我将items设置为依赖数组。不知何故,这导致 useEffect 继续运行。
  • 是的,这就是问题所在。现在我希望你知道原因后知道解决方案

标签: javascript reactjs react-hooks


【解决方案1】:

您在useEffect 中设置cart 并订阅它的更改,最终导致无限循环。从依赖数组中移除cart,所以它只在组件挂载时被调用一次。

useEffect(() => {
   setItems(getCart());
}, []);

您也不必使用cartTotal 函数。你可以依赖状态。

<span className={className}>{items.length}</span>

注意:记得为状态中的项目设置一个初始值。

const [items, setItems] = useState([]);

【讨论】:

  • 所以我应该包括 CartIcon 组件显示在导航栏上,该导航栏仅在整个应用程序中安装一次(除了 /signin 和 /signout 路径)。所以设置一个空数组意味着 useEffect 几乎不会在整个应用程序中再次运行。这样, CartIcon 中的项目数在我刷新之前不会改变。添加到购物车按钮也在不同的组件中。 LocalStorage 是 CartIcon 知道购物车中有多少商品的唯一方法。
  • @DavidQuartey 但是你不能直接监听本地存储的变化,至少使用useEffect。它完全取决于您希望如何以及何时从应用程序内部的存储中保存数据,但在每次渲染时保存它并不是最好的主意。我已经向您展示了 imo 最佳选择,仅在应用程序启动时从存储中获取数据一次,然后将其用于您的逻辑需求并在特定情况下更新存储内的数据,例如卸载组件,单击某些按钮等。
  • 作为一个电子商务应用程序,存储中的数据只有在用户将他们的第一个产品添加到购物车时才会设置。并且在整个用户会话期间,他们可以分别添加或删除项目。你说的方法我试过了,还是不行。是否可以只读取一次数据,仍然可以获得动态购物车图标效果?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 2021-11-21
相关资源
最近更新 更多