React useEffect:如何解决Maximum update depth exceeded无限循环错误?
问题修复:React组件无限循环(Maximum update depth exceeded)
问题原因
你的Landing组件触发无限循环,核心问题有两点:
- 当
userDetails不存在、userType不匹配任何分支时,没有对应的跳转逻辑,组件停留在当前页面,useEffect每次渲染都会执行redirectToDashboard,重复触发navigate - 即使匹配到
userType,如果目标路由配置错误(比如目标路由又重定向回Landing),或者重复调用navigate到当前路由,会触发组件重新渲染,进而再次执行useEffect形成循环
另外,redirectToDashboard函数每次组件渲染都会重新创建,你用eslint-disable忽略了依赖警告,这也可能隐藏潜在的依赖问题。
修复步骤
1. 完善分支逻辑,覆盖所有边界情况
在redirectToDashboard中添加默认分支,避免无意义的循环:
const redirectToDashboard = () => { if (isLoggedIn) { switch(userDetails?.userType) { case "CANDIDATE": navigate(ROUTES.CANDIDATE.DASHBOARD.PATH); break; case "COMPANY": navigate(ROUTES.COMPANY.DASHBOARD.PATH); break; case "ADMIN": navigate(ROUTES.ADMIN.DASHBOARD.PATH); break; default: // 处理未知用户类型,比如跳转到登录页或错误页 navigate(ROUTES.DEFAULT.PATH); } } else { navigate(ROUTES.DEFAULT.PATH); } };
2. 避免重复跳转,检查当前路由
跳转前先判断当前是否已经处于目标路由,防止重复调用navigate触发渲染:
首先引入useLocation:
import { useNavigate, useLocation } from "react-router-dom";
然后在组件中获取当前路径:
const location = useLocation();
修改redirectToDashboard:
const redirectToDashboard = () => { if (isLoggedIn) { let targetPath; switch(userDetails?.userType) { case "CANDIDATE": targetPath = ROUTES.CANDIDATE.DASHBOARD.PATH; break; case "COMPANY": targetPath = ROUTES.COMPANY.DASHBOARD.PATH; break; case "ADMIN": targetPath = ROUTES.ADMIN.DASHBOARD.PATH; break; default: targetPath = ROUTES.DEFAULT.PATH; } // 只有当前路径和目标路径不同时才跳转 if (location.pathname !== targetPath) { navigate(targetPath); } } else { const targetPath = ROUTES.DEFAULT.PATH; if (location.pathname !== targetPath) { navigate(targetPath); } } };
3. 优化依赖数组,消除ESLint警告
用useCallback包裹redirectToDashboard,确保函数引用稳定,同时把所有依赖加入useEffect的依赖数组:
import { useEffect, useCallback } from "react";
修改函数定义:
const redirectToDashboard = useCallback(() => { // ... 上面的逻辑 }, [isLoggedIn, userDetails, location, navigate, ROUTES]);
然后修改useEffect:
useEffect(() => { redirectToDashboard(); }, [redirectToDashboard]);
4. 检查路由配置
确认目标路由(比如ROUTES.CANDIDATE.DASHBOARD.PATH等)对应的组件没有重定向回Landing组件,确保路由跳转能正常完成。
最终修复后的代码
import { Spin } from "antd"; import { useEffect, useCallback } from "react"; import { useNavigate, useLocation } from "react-router-dom"; import { ROUTES } from "./Common/Constants"; const Landing = () => { const isLoggedIn = !!localStorage.getItem("authToken"); const userDetails = JSON.parse(localStorage.getItem("userDetails")); const navigate = useNavigate(); const location = useLocation(); const redirectToDashboard = useCallback(() => { if (isLoggedIn) { let targetPath; switch(userDetails?.userType) { case "CANDIDATE": targetPath = ROUTES.CANDIDATE.DASHBOARD.PATH; break; case "COMPANY": targetPath = ROUTES.COMPANY.DASHBOARD.PATH; break; case "ADMIN": targetPath = ROUTES.ADMIN.DASHBOARD.PATH; break; default: targetPath = ROUTES.DEFAULT.PATH; } if (location.pathname !== targetPath) { navigate(targetPath); } } else { const targetPath = ROUTES.DEFAULT.PATH; if (location.pathname !== targetPath) { navigate(targetPath); } } }, [isLoggedIn, userDetails, location, navigate, ROUTES]); useEffect(() => { redirectToDashboard(); }, [redirectToDashboard]); return <Spin fullscreen size="large" />; }; export default Landing;
内容的提问来源于stack exchange,提问作者Shruthi R
相关产品推荐
相关产品推荐

