🛣

react-router v6.4 で比較的型安全なルーティングを実現することで管理を楽にする

2022/09/23に公開

はじめに

react-router が v6.4 で比較的型安全なルーティングができるようになった?のでメモとして残しておきます。

以下のように作成することで、パス管理やルーティングの処理、遷移などが楽になります。

ファイル構成

今回関係のあるファイルは 📝 がついているものです。

vite で作成したアプリです。

yarn create vite {app_name} --template react-ts
.
├── index.html
├── package.json
├── public
│   └── vite.svg
├── src
│   ├── App.css
│   ├── App.tsx #📝
│   ├── assets
│   │   └── react.svg
│   ├── index.css
│   ├── main.tsx
│   ├── pages
│   │   ├── top
│   │   │   └── index.tsx #📝
│   │   └── users
│   │       └── [id]
│   │           └── index.tsx #📝
│   └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock

react-router-dom をインストール

https://reactrouter.com/en/main

yarn add react-router-dom

実装例

src/App.tsx
import { BrowserRouter, ParamParseKey, Route, Routes, useParams } from "react-router-dom";
import User from "./pages/users/[id]";
import "./App.css";
import Top from "./pages/top";

export const PATHS = {
  TOP: "/",
  ABOUT: "/about",
  USERS_ID: "/users/:id",
} as const;

// これでクエリパラメータの id が取り出せる
export const useParamsUsersId = useParams<ParamParseKey<typeof PATHS.USERS_ID>>;

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path={PATHS.TOP} element={<Top />} />
        <Route path={PATHS.ABOUT} element={<div>About</div>} />
        <Route path={PATHS.USERS_ID} element={<User />} />

        <Route path="*" element={<div>Not Found</div>} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
src/pages/top/index.tsx
import { generatePath } from "react-router-dom";
import { PATHS } from "../../App";

function Top() {
  return (
    <div>
      <h1>Top</h1>

      {/* generatePath で :id に代入できる */}
      <a href={generatePath(PATHS.USERS_ID, { id: "1" })}>User 1</a>
      <br />

      {/* これはエラー */}
      {/* Argument of type '{ userId: string; }' is not assignable to parameter of type '{ id: string; }'.
        Object literal may only specify known properties, and 'userId' does not exist in type '{ id: string; }' */}
      <a href={generatePath(PATHS.USERS_ID, { userId: "2" })}>User 2</a>
      <br />
      <a href={generatePath(PATHS.USERS_ID, { id: "3" })}>User 3</a>
    </div>
  );
}

export default Top;
src/pages/users/[id]/index.tsx
import { useParamsUsersId } from "../../../App";

function User() {
  const { id } = useParamsUsersId();
  return (
    <div>
      <h1>User</h1>
      <p>id: {id}</p>
    </div>
  );
}

export default User;

おわりに

これでルーティングの変更容易性が少しは上がりそうです 💪

GitHubで編集を提案

Discussion