React Router v6出现意外双重重定向问题,附相关代码求解决方案
问题根因
你遇到的反复跳转问题核心是路由配置生成逻辑和全局状态更新形成了渲染循环,触发react-router反复重匹配路由,具体问题点如下:
App.tsx每次重渲染都会调用routes(isLogged, dispatch)生成全新的路由配置数组,引用值每次变化会触发useRoutes重新执行路由匹配逻辑routes.ts函数内部存在会触发全局状态更新的逻辑:- 开头的
if (!localStorage.getItem('auth'))分支里,<Navigate to="/login" />是无效代码(没有被返回不会生效),但每次调用都会执行revokeUserInfo(dispatch)修改redux状态 - 内部定义的
revoke函数在每次生成路由配置时都会执行,一旦触发revokeUserInfo(dispatch)会修改isLogged状态,反过来触发App重渲染,再次生成新的路由配置,形成循环
- 开头的
- 路由配置里存在重复的重定向规则,进一步加剧了匹配逻辑的混乱
修复方案
1. 抽离静态路由配置
不要把路由配置定义成每次渲染都重新生成的函数,改成静态配置,权限校验逻辑单独处理:
// routes.ts 改成静态配置 export const routes = [ { path: 'app', element: <ProtectedRoute><DashboardLayout /></ProtectedRoute>, children: [ // 保持原有子路由配置不变,去掉动态的isLogged判断 ] }, { path: '/', element: <PublicRoute><MainLayout /></PublicRoute>, children: [ // 保持原有子路由配置不变 ] }, { path: '*', element: <Navigate to="/404" /> } ];
2. 新增路由守卫组件做权限校验
把鉴权逻辑放到单独的路由守卫组件的useEffect里,避免在渲染周期内直接修改状态:
// 受保护路由守卫 const ProtectedRoute = ({ children }) => { const { isLogged } = useSelector((state: RootStateType) => state.auth); const dispatch = useDispatch(); const navigate = useNavigate(); useEffect(() => { const auth = localStorage.getItem('auth'); if (!auth || (isLogged && isAuthExpired())) { revokeUserInfo(dispatch); navigate('/login', { replace: true }); } }, [isLogged, dispatch, navigate]); return isLogged ? children : <Navigate to="/login" replace />; }; // 公共路由守卫(已登录用户访问登录页等公共路由时跳转到首页) const PublicRoute = ({ children }) => { const { isLogged } = useSelector((state: RootStateType) => state.auth); return !isLogged ? children : <Navigate to="/app/dashboard" replace />; };
3. 简化App.tsx的路由调用
const App: FC = () => { const routing = useRoutes(routes); // 保持其余Provider逻辑不变 return ( <PersistGate loading={<Spinner />} persistor={persistor} > {/* 原有Provider保持不变 */} {routing} </PersistGate> ); };
额外注意
所有重定向操作尽量添加replace: true参数,避免在历史栈里插入多余的记录,进一步减少异常跳转的可能。
内容的提问来源于stack exchange,提问作者Stasya
相关产品推荐
相关产品推荐

