错误“超出最大更新深度。当组件在 useEffect 中调用 setState 时可能会发生这种情况”

新手上路,请多包涵

每当我的购物车组件(也在下面显示)被调用时,我都会遇到这个错误(重复数千次直到页面崩溃):

 index.js:1 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
    in Cart (created by Context.Consumer)
    in Route (at Routes.js:24)
    in Switch (at Routes.js:23)
    in Router (created by BrowserRouter)
    in BrowserRouter (at Routes.js:22)
    in Routes (at src/index.js:5)

我的购物车组件:

 import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import Layout from "./Layout";
import { getCart } from "./cartHelpers";
import Card from "./Card";
import Checkout from "./Checkout";

const Cart = () => {
    const [items, setItems] = useState([]);

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

    const showItems = items => {
        return (
            <div>
                <h2>Your cart has {`${items.length}`} items</h2>
                <hr />
                {items.map((product, i) => (
                    <Card
                        key={i}
                        product={product}
                        showAddToCartButton={false}
                        cartUpdate={true}
                        showRemoveProductButton={true}
                    />
                ))}
            </div>
        );
    };

    const noItemsMessage = () => (
        <h2>
            Your cart is empty. <br /> <Link to="/shop">Continue shopping</Link>
        </h2>
    );

    return (
        <Layout
            className="container-fluid"
        >
            <div className="row">
                <div className="col-6">
                    {items.length > 0 ? showItems(items) : noItemsMessage()}
                </div>

                <div className="col-6">
                    <h2 className="mb-4">Your cart summary</h2>
                    <hr />
                    <Checkout products={items} />
                </div>
            </div>
        </Layout>
    );
};

export default Cart;

useEffect 正在调用 getCart() (如下所示):

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

I intend for getCart to grab the cart from the localStorage and populate that in the state variable items or return an empty array [] .

根据我的理解,useEffect 会在状态发生变化时更改页面,并且当依赖项数组中有任何项目时,它将基于该项目。

好吧,我无法弄清楚为什么会发生此错误。

我真的试着理解这个错误 can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render 这是我到目前为止在尝试解决这个问题时学到的东西:

  1. items ,依赖关系,变化不大。测试添加 1 项或 0 项会导致数千个相同的错误
  2. 删除 useEffect 会完全停止错误, 但会破坏将其绑定到 项目 状态变量的目的

我怎样才能阻止这个错误?

我只想让这个组件在不冻结的情况下工作,并在渲染时抛出数千个错误。

原文由 rom 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 6.1k
2 个回答

原因在于您的 useEffect 依赖项:

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

问题是您正在传递 [items] 并在项目更改时调用 useEffect 。在 useEffect 中,您正在更改 items

确保每次从 getItems() 返回新对象或数组--- 反应不知道你的对象是相同的并且一次又一次地调用效果。

解决方案

从依赖项中删除项目

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

或者,如果您需要在更改时访问当前状态:

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

原文由 Dmitriy Kovalenko 发布,翻译遵循 CC BY-SA 4.0 许可协议

问题在这里:

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

您已添加依赖 items 。所以这意味着每当 items 更改时,运行 setItems(getCart());

但是,当您设置项目时,这意味着项目会发生变化,这又会再次触发 useEffect ,从而引发无限循环。

解决方案:

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

删除依赖项。这意味着 useEffect 将在组件为 mounted 时立即运行,并且仅执行一次。如果您出于不同的原因希望它运行,则需要将其添加到依赖项数组中。

原文由 Justsolarry 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题