ReactJS:本地存储超出最大更新深度

ReactJS: Maximum update depth exceeded with localstorage

我有一个登录页面,用户在其中对我的服务器进行身份验证。如果用户成功通过身份验证,那么我将设置 2 个本地存储密钥 - 一个用于 token,另一个用于 authtoken

用户可以在应用程序的页面之间导航,检查这些值是否存在没有任何问题。

当我注销时,注销按钮调用以下函数:

const handleLogout = () => {
    logout();
    history.replace("/");
};

logout()函数简单地清除上面提到的值:

localStorage.removeItem("token");
localStorage.removeItem("refreshToken");

问题是在注销时应用程序抛出以下异常:

Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

我最初认为问题出在登录页面组件中,但我在该组件上汇总了所有内容,而且我还创建了一个空白的新页面以重定向到,但出现了相同的异常结果。

只有当我注释掉对 logout() 的调用时,路由替换才能正常工作(当然不会从本地存储中删除值)。

localstorage 是否以我没有预料到的任何方式影响状态?怎么回事?

编辑

我找到了发生循环的地方。我有一个 Protected Route 组件,如下所示:

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { isAuthenticated } from "../../services/api/auth";

function ProtectedRoute({
    component: Component,
    children: ChildComponent,
    ...rest
}) {
    return (
        <Route
            {...rest}
            render={(props) => {
                if (isAuthenticated()) {
                    return (
                        (Component && <Component {...props} />) ||
                        ChildComponent
                    );
                } else {
                    return (
                        <Redirect
                            to={{
                                pathname: "/",
                                state: { from: props.location },
                            }}
                        />
                    );
                }
            }}
        />
    );
}

export default ProtectedRoute;

logout() 被调用并且 history.replace("/"); 发生时,它代表我的页面调用此组件(卸载?)为什么它在 "/" 页面时呈现此页面被重定向到没有使用这个组件?

我找到了我的特定问题的答案。但由于我已经从网上的一篇文章中了解了如何创建受保护的路由,这可能对可能遇到此问题但不明白为什么的其他人有用。

问题出在 ProtectedRoute 组件中。每次更改页面时都会调用它(也在空的 React 应用程序上检查)。当它在 Route 组件中调用 render 时,它会计算 isAuthenticated()。由于身份验证数据被删除,这是错误的,因此属于 Redirect 组件,这再次导致 ProtectedRoute 成为 re-rendered - 一次又一次 - 因此 - 一个循环。

为了解决这个问题,我在组件中添加了一个列表,其中包含未受保护的路由,如果身份验证失败并且它们是活动路由,则应忽略这些路由:

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { useLocation } from "react-router-dom";
import { isAuthenticated } from "../../services/api/auth";

function ProtectedRoute({
    component: Component,
    children: ChildComponent,
    ...rest
}) {
    const location = useLocation();
    const unProtectedPaths = ["/"];

    return (
        <Route
            {...rest}
            render={(props) => {
                if (isAuthenticated()) {
                    return (
                        (Component && <Component {...props} />) ||
                        ChildComponent
                    );
                } else if (!unProtectedPaths.includes(location.pathname)) {
                    return (
                        <Redirect
                            to={{
                                pathname: "/",
                                state: { from: props.location },
                            }}
                        />
                    );
                }
            }}
        />
    );
}

export default ProtectedRoute;