使用 useEffect 钩子时无法对未安装的组件执行 React 状态更新

使用useEffect钩子时,我似乎收到以下错误

警告:无法对卸载的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。

我相信它与我调用的异步函数有关,以设置用户是否经过身份验证。

ProtectedRoute.tsx

export function ProtectedRoute({ ...routeProps }: ProtectedRouteProps): ReactElement | null {
    const context = useContext(AppContext);
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    useEffect(() => {
        isUserAuthenticated(context.token).then(setIsAuthenticated).catch(setIsAuthenticated);
    });

    if (isAuthenticated) {
        return <Route {...routeProps} />;
    } else {
        return <Redirect to={{ pathname: "login" }} />;
    }
}

const isUserAuthenticated = async (token: any): Promise<boolean> => {
    try {
        const response = await VerifyAuthentication(token);
        console.log("VerifyAuthentication", response);
        if (response.status !== 200) {
            return false;
        }

        return true;
    } catch (err) {
        return false;
    }
};

应用程序.tsx

class App extends Component<Props, State> {
    renderRouter = () => {
        return (
            <Router>
                <Switch>
                    <ProtectedRoute exact path="/" component={Dashboard} />
                    <Route exact path="/login" component={Login} />
                </Switch>
            </Router>
        );
    };

    render(): ReactElement {
        return (
            <div className="App">
                <AppProvider>
                    <Theme>
                        <Sidebar>{this.renderRouter()}</Sidebar>
                    </Theme>
                </AppProvider>
            </div>
        );
    }
}
大卫

大概这会将用户重定向到没有此组件的路由:

return <Redirect to={{ pathname: "login" }} />;

这意味着组件已卸载,或者通常从活动使用/内存中卸载。总是发生,因为这种情况永远不会true

if (isAuthenticated) {

因为当组件首次呈现该值时,该值显式设置为false

const [isAuthenticated, setIsAuthenticated] = useState(false);

所以基本上发生的事情是:

  1. 您触发异步操作以检查用户是否通过身份验证。
  2. 在等待响应之前,您决定用户未通过身份验证并重定向他们。
  3. 由于用户已离开此页面,组件被卸载。
  4. 收到异步响应并尝试更新不再加载/安装的组件的状态。

尚不完全清楚该组件打算如何适应您的整体结构,但您将需要更改该结构。检查身份验证需要同步,或者您需要在重定向之前等待异步操作完成。后者的一个例子可能很简单:

export function ProtectedRoute({ ...routeProps }: ProtectedRouteProps): ReactElement | null {
  const context = useContext(AppContext);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    isUserAuthenticated(context.token)
      .then(x => {
        setIsAuthenticated(x);
        setIsLoading(false);
      })
      .catch(e => {
        setIsAuthenticated(false);
        setIsLoading(false);
        console.log(e);
      });
  });

  if (isLoading) {
    return <div>Loading...</div>;
  } else if (isAuthenticated) {
    return <Route {...routeProps} />;
  } else {
    return <Redirect to={{ pathname: "login" }} />;
  }
}

在这种情况下,单独的状态值isLoading用于跟踪异步操作是否仍在发生,因此组件“等待”直到数据加载,然后再决定是否重定向用户。

但总的来说,我不明白为什么身份验证检查不能同步。更高级别的东西,例如将整个应用程序结构包装在 中的提供者组件<App/>,可以具有上述相同的逻辑,本质上执行异步操作并将结果保持在状态。然后可以通过useContext或 Redux提供该状态,甚至可以将其作为道具传递给所有子组件。

您不需要在子组件中一遍又一遍地重新检查身份验证。这是应用程序级别的问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

React 状态无法使用 UseEffect 更新

React useEffect导致:无法在未安装的组件上执行React状态更新

UseEffect 挂钩错误,无法对未安装的组件执行 React 状态更新

useEffect-无法在未安装的组件上执行React状态更新

React挂钩:使用useEffect时无法获取状态更新

无法对已卸载的组件useEffect执行React状态更新

Next.js 仅在桌面上渲染视频:useEffect 无法对未安装的组件执行 React 状态更新

React Native - 无法对未安装的组件执行 React 状态更新,使用效果清理功能

无法使用 react-router-dom 链接对未安装的组件执行 React 状态更新

无法使用获取POST方法在未安装的组件上执行React状态更新

无法从useEffect更新React状态挂钩

使用 React 钩子从另一个页面使用 useEffect 更新状态

React无法对未安装的组件错误执行React状态更新

React - 无法对未安装的组件执行 React 状态更新

React:无法在未安装的组件上执行React状态更新

无法对 reactjs 中未安装的组件执行 React 状态更新

ReactJS:无法在未安装的组件上执行React状态更新

无法在未安装的组件上执行React状态更新

如何使用 useEffect 从 Redux 商店中的状态更新 React UI

React如何使用useEffect监视和更新状态?

状态值在 UseEffect 钩子内停止更新 - Gatsby/React

组件未使用'useEffect'钩子在React中重新渲染

使用React钩子时使用打字稿键入组件状态

状态更新后,React useEffect不会重新加载组件

在useEffect中添加了isCancelled标志,但仍显示“无法在已卸载的组件上执行React状态更新...”

无法在已卸载的组件上执行React状态更新。取消useEffect中的所有任务

警告:无法在已卸载的组件上执行React状态更新。useEffect清理功能

React.useEffect:axios请求后状态未更新

React 如何使用 useEffect 和 useCallback 重新渲染状态钩子?