TanStack Router 入門:型安全なルーティングの基本

スポンサーリンク

TanStack Router 入門:型安全なルーティングの基本

TanStack Routerとは

TanStack RouterはReact向けの型安全なルーティングライブラリです。URLパラメータやクエリパラメータまでTypeScriptの型が効き、遷移先のパスも補完されます。React Router v6と比べてTypeScriptとの統合が強力です。


React Router v6との主な違い

React Router v6 TanStack Router
型安全 △(パラメータは手動で型定義) ◎(ルート定義から型が自動で付く)
ファイルベースルーティング なし あり(オプション)
検索パラメータ 手動でパース スキーマで定義して型付き
ローダー(データフェッチ) なし ルートに直接定義可

インストール

npm install @tanstack/react-router

コードベースルーティング(基本)

ルートを定義する

// src/router.tsx
import { createRouter, createRoute, createRootRoute } from '@tanstack/react-router'
import Home from './pages/Home'
import About from './pages/About'

const rootRoute = createRootRoute({
  component: () => (
    <div>
      <nav>
        <Link to="/">ホーム</Link>
        <Link to="/about">About</Link>
      </nav>
      <Outlet />
    </div>
  ),
})

const homeRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/',
  component: Home,
})

const aboutRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/about',
  component: About,
})

const routeTree = rootRoute.addChildren([homeRoute, aboutRoute])

export const router = createRouter({ routeTree })

// TypeScriptの型登録
declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}

Providerで囲む

// src/main.tsx
import { RouterProvider } from '@tanstack/react-router'
import { router } from './router'

createRoot(document.getElementById('root')!).render(
  <RouterProvider router={router} />
)

Linkで遷移する

to の値が補完されます。存在しないパスはTypeScriptエラーになります。

import { Link } from '@tanstack/react-router'

function Nav() {
  return (
    <nav>
      <Link to="/">ホーム</Link>
      <Link to="/about">About</Link>
    </nav>
  )
}

URLパラメータ

const userRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/users/$id', // $id がパラメータ
  component: UserDetail,
})

function UserDetail() {
  const { id } = userRoute.useParams() // 型が付いている
  return <p>ユーザーID: {id}</p>
}

検索パラメータ(型安全)

import { z } from 'zod'

const searchRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/search',
  validateSearch: z.object({
    q: z.string().default(''),
    page: z.number().default(1),
  }),
  component: SearchPage,
})

function SearchPage() {
  const { q, page } = searchRoute.useSearch() // q: string, page: number が確定
  return <p>{q} - {page}ページ目</p>
}

useNavigateでプログラム遷移

import { useNavigate } from '@tanstack/react-router'

function LoginForm() {
  const navigate = useNavigate()

  const handleLogin = async () => {
    await login()
    navigate({ to: '/dashboard' }) // パスが補完される
  }

  return <button onClick={handleLogin}>ログイン</button>
}

ローダーでデータを事前取得する

ルートに loader を定義すると、コンポーネントが描画される前にデータを取得できます。

const userRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/users/$id',
  loader: async ({ params }) => {
    const user = await fetch(`/api/users/${params.id}`).then((r) => r.json())
    return { user }
  },
  component: UserDetail,
})

function UserDetail() {
  const { user } = userRoute.useLoaderData() // 型が付いている
  return <p>{user.name}</p>
}

まとめ

API 用途
createRootRoute ルートの親ルートを作成
createRoute 各ルートを定義
RouterProvider ルーターのProvider
Link 型安全なリンク
useNavigate プログラム遷移
useParams URLパラメータ(型付き)
useSearch 検索パラメータ(型付き)
loader ルートのデータ事前取得
  • TypeScriptプロジェクトではReact Routerより型安全に書ける
  • 検索パラメータをスキーマで定義できるのが強み
  • ファイルベースルーティングも使えるが、コードベースでも十分シンプル

Reactのプロジェクト作成から始める場合は「React + Vite でプロジェクト作成」を参照してください。

React Router v6の基本は「React Router v6 入門」を参照してください。