普通文組 2.5

快速筆記:在 react-router-dom 5 實作條件路由

總結

目前手上有一個專案是使用 react 18 搭配 react-router-dom 5 來進行開發,在實作「條件式路由+懶載入」的途中,持續遇到「進入不存在的路由時,404 畫面消失,畫面只剩一片空白」的情況。此篇筆記將記錄一下最後能順利作用的程式碼為何。

版本與環境

react: 18.2.0
react-router-dom: 5.3.4

筆記

需求描述

  • 使用 react 的 lazy 搭配 Suspense 元件
  • 根據 env.isDevelopment 來決定是否要讓使用者進入 /something-develop-only 這個畫面,在非開發環境下,試圖進入 /something-develop-only 的使用者會被送到 /404
  • 暫不考慮使用帳號系統來做權限管理

程式碼

重點:

  • React.Suspense 要包在 Switch 外層
  • 作為 React.Suspense 的 fallback 元件不使用懶載入
import React, { lazy, Suspense } from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import Loading from "@Component/Page/Loading";
import env from "@Model/env";
const Landing = lazy(() => import("@Component/Page/Landing"));
const SomePage = lazy(() => import("@Component/Page/SomePage"));
const DevelopmentOnly = lazy(() => import("@Component/Page/DevelopmentOnly"));
const NotFound = lazy(() => import("@Component/Page/NotFound"));

function Router(): React.ReactElement {
  return (
    <BrowserRouter>
      <Suspense fallback={<Loading />}>
        <Switch>
          <Route path="/" exact>
            <Landing />
          </Route>
          <Route path="/page1">
            <SomePage />
          </Route>
          <Route path="/development-only" exact>
            {env.isDevelopment ? <DevelopmentOnly /> : <Redirect to="/404" />}
          </Route>
          <Route path="/404">
            <NotFound />
          </Route>
          <Route path="*">
            <Redirect to="/404" />
          </Route>
        </Switch>
      </Suspense>
    </BrowserRouter>
  );
}

export default Router;

備註:以下兩種寫法可以互換,效果相同

寫法ㄧ:根據 env.isDevelopment 與否決定顯示 DevelopmentOnlyRedirect 元件

<Route path="/develop-only" exact>
  {env.isDevelopment ? <DevelopmentOnly /> : <Redirect to="/404" />}
</Route>

寫法二:根據 env.isDevelopment 來決定是否要在 Switch 元件內顯示 /develop-only 這條路由的 Route 元件

{
  env.isDevelopment && (
    <Route path="/develop-only" exact>
      <DevelopmentOnly />
    </Route>
  );
}

參考文件