React基于localStorage判断跳转时报Maximum update depth exceeded错误如何解决
问题根因
- 你在工具文件中导出的
user是模块加载时一次性计算的静态常量,仅在首次导入工具文件时读取一次localStorage,后续localStorage的更新(登录/退出操作)不会同步更新这个常量的值。 - 触发无限更新的原因是:未登录状态下这个常量永远为假值,组件每次渲染都会触发重定向,当路由匹配逻辑存在重复触发渲染的情况时,就会进入重定向→渲染→重定向的死循环。你在组件内部每次渲染都实时读取localStorage的话,登录后值会更新,就能跳出循环,因此不会报错。
最优复用方案
方案1:封装工具函数(改动最小)
不要导出静态常量,改为导出每次调用都读取最新localStorage的函数:
// utils/auth.js export const getCurrentUser = () => { const userStr = localStorage.getItem('user'); return userStr ? JSON.parse(userStr) : null; };
业务组件使用:
import { getCurrentUser } from '../../utils/auth'; const Dashboard = () => { const user = getCurrentUser(); if (!user) return <Redirect to='/auth' />; return <h1>Dashboard</h1>; };
方案2:封装路由守卫(复用性最高,无需每个组件写判断)
直接封装私有路由组件,所有需要登录权限的路由统一用该组件包裹,完全不用在业务页面写登录判断:
React Router v5 版本
// components/PrivateRoute.js import { Route, Redirect } from 'react-router-dom'; import { getCurrentUser } from '../utils/auth'; const PrivateRoute = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={props => getCurrentUser() ? <Component {...props} /> : <Redirect to='/auth' /> } /> ); }; export default PrivateRoute;
路由配置使用:
import { Switch } from 'react-router-dom'; import PrivateRoute from './components/PrivateRoute'; const App = () => { return ( <Switch> <Route path='/auth' component={AuthPage} /> {/* 所有需要登录的路由统一使用PrivateRoute */} <PrivateRoute path='/dashboard' component={Dashboard} /> <PrivateRoute path='/profile' component={Profile} /> </Switch> ); };
React Router v6 版本
// components/PrivateRoute.js import { Navigate, Outlet } from 'react-router-dom'; import { getCurrentUser } from '../utils/auth'; const PrivateRoute = () => { return getCurrentUser() ? <Outlet /> : <Navigate to='/auth' />; }; export default PrivateRoute;
路由配置使用:
import { Routes, Route } from 'react-router-dom'; import PrivateRoute from './components/PrivateRoute'; const App = () => { return ( <Routes> <Route path='/auth' element={<AuthPage />} /> <Route element={<PrivateRoute />}> {/* 该节点下所有子路由自动继承登录校验 */} <Route path='/dashboard' element={<Dashboard />} /> <Route path='/profile' element={<Profile />} /> </Route> </Routes> ); };
方案3:封装自定义Hook(适合需要频繁使用用户信息的场景)
// hooks/useCurrentUser.js import { useMemo } from 'react'; import { getCurrentUser } from '../utils/auth'; export const useCurrentUser = () => { return useMemo(() => getCurrentUser(), []); };
业务组件使用:
import { useCurrentUser } from '../hooks/useCurrentUser'; const Dashboard = () => { const user = useCurrentUser(); if (!user) return <Redirect to='/auth' />; return <h1>欢迎回来,{user.nickname}</h1>; };
内容的提问来源于stack exchange,提问作者Nemus
相关产品推荐
相关产品推荐

