react-router-dom v6中Navigate组件与Routes location冲突致无限渲染
问题原因
当访问不匹配的URL时,通配路由的<Navigate to="/home" />会触发路由跳转,导致location.pathname更新。而TransitionGroup在过渡动画期间会同时保留旧的和新的CSSTransition组件,旧组件内的Routes仍使用旧的无效路径,会再次渲染<Navigate>触发跳转,形成无限循环,最终触发“超过最大更新深度”错误。
解决方案
方案一:将重定向逻辑移到顶层路由(推荐)
把通配路由的重定向放在TransitionGroup之外的顶层Routes中,确保无效路径直接被重定向,不会进入过渡组件引发循环:
import { FC } from 'react'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { Routes, Route, useLocation, Navigate, Outlet } from 'react-router-dom'; // 封装带转场的Outlet组件 const TransitionOutlet: FC = () => { const location = useLocation(); return ( <CSSTransition key={location.pathname} classNames="page" timeout={1000}> <div> <Outlet /> </div> </CSSTransition> ); }; const Router: FC = () => { return ( <Routes> {/* 优先处理重定向,直接跳转到home */} <Route path="*" element={<Navigate to="/home" replace />} /> {/* 所有需要转场的路由嵌套在此 */} <Route element={<TransitionGroup><TransitionOutlet /></TransitionGroup>}> <Route path="/home" element={<div>Home</div>} /> <Route path="/user" element={<div>User</div>} /> </Route> </Routes> ); }; export default Router;
方案二:给CSSTransition添加卸载控制属性
通过mountOnEnter和unmountOnExit属性,确保旧组件在过渡动画完成后立即卸载,避免旧组件内的Navigate重复触发跳转:
import { FC } from 'react'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { Routes, Route, useLocation, Navigate } from 'react-router-dom'; const Router: FC = () => { const location = useLocation(); return ( <TransitionGroup> <CSSTransition key={location.pathname} classNames={"page"} timeout={1000} mountOnEnter unmountOnExit > <div> <Routes location={location}> <Route path="/home" element={<div>Home</div>} /> <Route path="/user" element={<div>User</div>} /> <Route path="*" element={<Navigate to={'/home'} replace />} /> </Routes> </div> </CSSTransition > </TransitionGroup > ); }; export default Router;
内容的提问来源于stack exchange,提问作者Anastasia
相关产品推荐
相关产品推荐

