React Router 5.1.2嵌套路由如何仅渲染子组件隐藏父组件?
React Router 6 实现点击父组件后仅渲染子组件
在React Router 6中,原5.x版本的嵌套路由默认会同时渲染父组件和子组件内容,要实现点击后仅显示子组件,可以通过两种方式调整路由结构:
方式一:拆分平行路由
将父、子路由设置为同级,利用Routes的精确匹配特性,访问子路由时直接替换父组件的渲染内容。
改造后的完整代码
import { BrowserRouter as Router, Routes, Route, Link, useParams } from "react-router-dom"; const topics = [ { name: "React基础", id: "react-basic", description: "React核心概念与基础用法", resources: [ { name: "JSX语法", id: "jsx", description: "React的XML-like语法扩展", url: "https://react.dev/learn/writing-markup-with-jsx", }, { name: "组件生命周期", id: "lifecycle", description: "组件从创建到销毁的阶段", url: "https://react.dev/reference/react/Component#lifecycle-methods", }, ], }, { name: "状态管理", id: "state-management", description: "React应用状态管理方案", resources: [ { name: "useState Hook", id: "usestate", description: "组件内部状态管理", url: "https://react.dev/reference/react/useState", }, { name: "Redux基础", id: "redux-basic", description: "全局状态管理工具", url: "https://redux.js.org/introduction/getting-started", }, ], }, ]; function Home() { return <h1>HOME</h1>; } function Resource() { const { topicId, subId } = useParams(); const topic = topics .find(({ id }) => id === topicId) .resources.find(({ id }) => id === subId); return ( <div> <h3>{topic.name}</h3> <p>{topic.description}</p> <a href={topic.url}>查看详情</a> </div> ); } function Topic() { const { topicId } = useParams(); const topic = topics.find(({ id }) => id === topicId); return ( <div> <h2>{topic.name}</h2> <p>{topic.description}</p> <ul> {topic.resources.map((sub) => ( <li key={sub.id}> <Link to={`/topics/${topicId}/${sub.id}`}>{sub.name}</Link> </li> ))} </ul> </div> ); } function Topics() { return ( <div> <h1>Topics</h1> <ul> {topics.map(({ name, id }) => ( <li key={id}> <Link to={`/topics/${id}`}>{name}</Link> </li> ))} </ul> </div> ); } export default function App() { return ( <Router> <div style={{ width: 1000, margin: "0 auto" }}> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/topics">Topics</Link> </li> </ul> <hr /> <Routes> <Route path="/" element={<Home />} /> <Route path="/topics" element={<Topics />} /> <Route path="/topics/:topicId" element={<Topic />} /> <Route path="/topics/:topicId/:subId" element={<Resource />} /> </Routes> </div> </Router> ); }
效果说明:
- 访问
/topics:仅显示Topics列表 - 访问
/topics/:topicId:仅显示对应Topic的内容和子资源列表 - 访问
/topics/:topicId/:subId:仅显示对应Resource的详情
方式二:嵌套路由+条件渲染
如果需要保留路由嵌套结构,可通过useMatch判断当前路由是否匹配子路由,条件渲染父组件内容。
核心代码改造
import { useMatch, Outlet } from "react-router-dom"; // Topic组件改造 function Topic() { const { topicId } = useParams(); const topic = topics.find(({ id }) => id === topicId); // 判断是否匹配子路由 const hasSubRoute = useMatch("/topics/:topicId/:subId"); return ( <div> {/* 仅当没有子路由匹配时,渲染父组件内容 */} {!hasSubRoute && ( <> <h2>{topic.name}</h2> <p>{topic.description}</p> <ul> {topic.resources.map((sub) => ( <li key={sub.id}> <Link to={`/topics/${topicId}/${sub.id}`}>{sub.name}</Link> </li> ))} </ul> <hr /> </> )} {/* 渲染子路由组件 */} <Outlet /> </div> ); } // App路由改造 export default function App() { return ( <Router> <div style={{ width: 1000, margin: "0 auto" }}> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/topics">Topics</Link> </li> </ul> <hr /> <Routes> <Route path="/" element={<Home />} /> <Route path="/topics" element={<Topics />}> <Route path=":topicId" element={<Topic />}> <Route path=":subId" element={<Resource />} /> </Route> </Route> </Routes> </div> </Router> ); }
效果说明:
- 访问
/topics/:topicId:显示Topic内容+子资源列表 - 点击子资源链接后,自动隐藏Topic内容,仅显示Resource详情
内容的提问来源于stack exchange,提问作者Lajos Hufnagel
相关产品推荐
相关产品推荐

