正确地构建 React 嵌套路由

211 阅读1分钟

路由结构

graph TD
设计模式 --> 面向对象原则
设计模式 --> GoF设计模式
设计模式 --> 统一建模语言
GoF设计模式 --> 适配器模式
GoF设计模式 --> 装饰者模式
GoF设计模式 --> 桥接模式

静态路由表

ReactDOM.render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App></App>}>
        <Route index element={<GOF />}></Route>
        <Route path="gof" element={<GOF />}>
          <Route index element={<Adapter />}></Route>
          <Route path="adapter" element={<Adapter />}></Route>
          <Route path="appearance" element={<Appearance />}></Route>
          <Route path="bridge" element={<Bridge />}></Route>
        </Route>
        <Route path="oop" element={<OOP />}></Route>
        <Route path="uml" element={<UML />}></Route>
      </Route>
      <Route path="*" element={<NotFound />} />
    </Routes>
  </BrowserRouter>,
  document.getElementById("app")
);

在 App 页面放置路由出口 Outlet

export default function App() {
  const navigate = useNavigate();
  return (
    <ConfigProvider>
      <Layout className="app">
        <Header>
          <Menu mode="horizontal">
            <Menu.Item key="gof">GoF设计模式</Menu.Item>
            <Menu.Item key="oop">面向对象原则</Menu.Item>
            <Menu.Item key="uml">统一建模语言</Menu.Item>
          </Menu>
        </Header>
        <Outlet></Outlet>
      </Layout>
    </ConfigProvider>
  );
}

在 GOF 页面放置路由出口 Outlet

export default function GOF() {
  const navigate = useNavigate();
  return (
    <Layout className="content">
      <Sider width={256}>
        ......
      </Sider>
      <Content>
        <Outlet></Outlet>
      </Content>
    </Layout>
  );
}

无状态组件使用 useNavigate 进行路由跳转

navigate(`/gof/${params}`);

疑难问题

在地址栏中输入 /gof 时惊讶发现返回 404。百思不解。之所以百思不解的原因是缺少前置背景知识。不理解 BrowserRouterHashRouter 的差别。使用 BrowserRouter,需要记住一点:/gof会被当作请求的一部分发送到服务端。服务端如果没有对应的路由就会报错。在采用BrowserRouter,服务端一般将任何路径请求都重定向到根路径。

解决方案:服务端将所有的路径请求都重定向到根路径。在本地开发时,解决这个问题的方式是在webpack中添加如下配置

  devServer: {
    historyApiFallback: true,
  },

或者不采用 BrowserRouter 模式,采用 HashRouter模式。

完整效果

Jietu20220207-010318.png

完整案例

design-pattern