📌

react-router-domでファイルシステムベースのルーティングをする方法

2024/04/12に公開

前準備

プロジェクト作成

$ npm create vite@latest
✔ Project name: … hoge-app
✔ Select a framework: › React
✔ Select a variant: › TypeScript + SWC

$ cd hoge-app
$ npm i
$ npm i react-router-dom
$ npm run dev

上記設定で、viteとReactのプロジェクトを作成し、立ち上がるところまで確認しておく
(プロジェクト名は何でも良いし、SWC無しのTypeScriptでも動く)

ファイル作成

# フォルダ作成と不要ファイル削除
$ mkdir src/pages
$ rm -rf src/App.tsx src/App.css
# 2ファイル作成しておく
cat << \EOF > ./src/pages/Index.tsx
export default function Index() {
  return (
    <div>
      <p className="read-the-docs">
        ✨ top!!</p>
      <a href="/">topへ</a>
      <a href="/page1">page1へ</a>
    </div>
  )
}
EOF

cat << \EOF > ./src/pages/Page1.tsx
export default function Page1() {
  return (
    <div>
      <p className="read-the-docs">
        ✨ page1 ✨
      </p>
      <a href="/">topへ</a>
      <a href="/page1">page1へ</a>
    </div>
  )
}
EOF

実際のコード

/src/main.tsx を下記で上書きする

import * as React from "react";
import { createRoot } from "react-dom/client";
import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

const ROUTES = import.meta.glob(
  '/src/pages/**/[A-Z]*.tsx',
   { import: 'default', eager: true }
)

const routes = Object.keys(ROUTES).map((route) => {
  const path = route
    .replace(/\/src\/pages|Index|\.tsx$/g, '')
    .replace(/\[\.{3}.+\]/, '*')
    .replace(/\[(.+)\]/, ':$1')
    .toLowerCase()

  const Component = ROUTES[route] as React.ComponentType;

  return { path, element: <Component />}
})
const router = createBrowserRouter(routes);

createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

バージョン情報

{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.22.3"
  },
  "devDependencies": {
    "@types/react": "^18.2.66",
    "@types/react-dom": "^18.2.22",
    "@typescript-eslint/eslint-plugin": "^7.2.0",
    "@typescript-eslint/parser": "^7.2.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "eslint": "^8.57.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.6",
    "typescript": "^5.2.2",
    "vite": "^5.2.0"
  }
}

ひとこと

Next.jsのファイルシステムベースのルーティング良いなぁと思っていたのですが、Vite+react-router-domでも、できるなと。

Viteのほうが起動やHMRが速いし、Laravel + Vite など、Viteを使う必要がある場合にも、有用だなと。

参考記事

File-based routing with React Router — Upgrading to v6

参考記事の通りにすると、うまくいかなかったので、それなりに変更しています。

Discussion