You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:01:00