如何用react-router-dom实现/programs路由自动重定向到默认子路由?
问题描述
我使用react-router-dom搭建路由,其中/programs路由会渲染侧边导航栏和<Outlet/>。当访问/programs时,<Outlet/>区域为空,希望用户输入/programs URL时自动跳转到/programs/myprograms。此前使用<Navigate/>(原redirect())会先渲染整个页面,想找更优的实现方式。
现有路由配置
const router = createBrowserRouter([ { path: "/", element: <Root />, errorElement: <Error />, children: [ { path: "/", element: <Home /> }, { path: "progress", element: <Progress /> }, { path: "logworkout", element: <LogWorkout /> }, { path: "programs", element: <Programs />, children: [ { path: "discover", element: <DiscoverPrograms /> }, { path: "myprograms", element: <MyPrograms /> }, ], }, { path: "product", element: <Product /> }, { path: "contact", element: <Contact /> }, ], }, ]);
Programs组件代码
import SideBar from "../../components/Programs/SideBar"; import { Outlet } from "react-router-dom"; const Programs = () => { return ( <div className="grid overflow-hidden" style={{gridTemplateColumns: "auto 1fr"}}> <SideBar /> <div className="overflow-auto"> <Outlet /> </div> </div> ); }; export default Programs;
最优实现方案
在react-router-dom v6中,最推荐的方式是通过添加index路由处理父路由根路径的跳转,这种方式不会先渲染父组件内容,直接完成路由重定向,彻底避免页面闪烁问题。
方法1:添加index路由(优先选择)
修改路由配置,给programs的子路由新增一个index路由,使用<Navigate replace to="myprograms" />作为元素:
const router = createBrowserRouter([ { path: "/", element: <Root />, errorElement: <Error />, children: [ { path: "/", element: <Home /> }, { path: "progress", element: <Progress /> }, { path: "logworkout", element: <LogWorkout /> }, { path: "programs", element: <Programs />, children: [ // 新增index路由,处理/programs根路径跳转 { index: true, element: <Navigate replace to="myprograms" /> }, { path: "discover", element: <DiscoverPrograms /> }, { path: "myprograms", element: <MyPrograms /> }, ], }, { path: "product", element: <Product /> }, { path: "contact", element: <Contact /> }, ], }, ]);
这里的replace属性会替换浏览器历史记录中的当前条目,用户点击返回时不会回到空的/programs页面,体验更流畅。
方法2:组件内处理(备选方案)
如果不想修改路由配置,也可以在Programs组件内通过钩子判断路径后跳转,但这种方式仍会先渲染侧边栏再跳转,不如方法1高效:
import SideBar from "../../components/Programs/SideBar"; import { Outlet, useLocation, useNavigate, useEffect } from "react-router-dom"; const Programs = () => { const location = useLocation(); const navigate = useNavigate(); useEffect(() => { if (location.pathname === "/programs") { navigate("myprograms", { replace: true }); } }, [location.pathname, navigate]); return ( <div className="grid overflow-hidden" style={{gridTemplateColumns: "auto 1fr"}}> <SideBar /> <div className="overflow-auto"> <Outlet /> </div> </div> ); }; export default Programs;
内容的提问来源于stack exchange,提问作者Jia Huang
相关产品推荐
相关产品推荐

