mcpField
T
tanstack-router

tanstack-router

github.com/bm629開発796 回インストール2 週間前に更新
リポジトリ

tanstack-router について

tanstack-routerは、React SPAでTanStack Routerを設定、拡張するためのスキルです。型安全なルーティング、検証済みURL検索状態、ローダー、ルーティング層でのTanStack Query連携、ルート付きコンポーネントのテストを扱います。

主な機能

  1. 01型安全なルート定義とナビゲーション
  2. 02ファイルベースとコードベースのルーティング
  3. 03検証済み検索パラメーター
  4. 04ルートローダーとプリロード
  5. 05TanStack Queryとローダーの連携
  6. 06インメモリのルート付きコンポーネントテスト

活用シーン

  1. 01React SPAのルーティング設定
  2. 02型付きルートと検索状態の追加
  3. 03TanStack Queryによるルートデータの先読み
  4. 04ルーターが必要なコンポーネントのテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bm629/agent-skills --skill tanstack-router

インストール後、Claude Code で/tanstack-routerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
auth-and-testing.md
navigation-and-splitting.md
query-integration.md
routing-approaches.md
search-and-loaders.md
sources.md

詳細

tanstack-router — SKILL.md

バリアント: 標準 · 使用するタイミング: スキルが呼び出され、内容を読み、TanStack Router アプリをセットアップまたは拡張すると、呼び出し元に制御が戻ります。

@tanstack/react-router v1(1.170.x)、および2026-06時点のTanStack Routerドキュメントに照らして検証済みです。 TanStack Routerのメジャーバージョンはv1です(継続的にリリースされるsemverのマイナーリリース)。以下のAPIは、作成時点で公式のtanstack.com/routerドキュメントと照合しています。オプション名はバージョンによって異なる場合があります。使用中のバージョンで名前が404になる場合は、references/sources.mdに記載されている該当バージョンのドキュメントページを確認してください。

概要

TanStack Routerは、React SPA向けの完全な型安全性を備えたクライアントサイドルーターです。特徴は、ルートツリーが型のソースになることです。TypeScriptの宣言マージでルーターを登録すると、すべてのLink、navigate、useParams、useSearch、useLoaderDataが実際のルートに照らしてチェックされます。そのため、無効なパスや不足しているパラメーターはコンパイルエラーになります。ファーストクラスの検索パラメーター(スキーマで検証されるURLの状態)、ルートローダー(プリロード可能な、レンダリング前に取得されるデータ)、およびコード分割を備えています。このスキルでは、ルーターをセットアップし、型安全にルートを接続し、ローダーからデータ取得へのつなぎ目(TanStack Queryとの連携を含む)と、ルーティングされたコンポーネント用のテストハーネスを扱います。これはルーティングレイヤーです。フルスタックフレームワークのTanStack Startはその上に構築されます(ここでは対象外です。「適用範囲」を参照してください)。

使用するタイミング

  • ✅ Vite + React + TypeScriptのSPAでルーティングをセットアップする(または既存のTanStack Routerアプリを拡張する)。
  • ✅ ルート、型付きナビゲーション、検証済み検索パラメーター、またはルートローダーを定義する。
  • ✅ ルートローダーをTanStack Queryに接続する(ローダーでプリフェッチし、コンポーネントで読み取る)。
  • ✅ ルーティングされたコンポーネントをレンダリングするテストを書く(メモリ履歴ハーネスが必要)。

次の場合は有効にしないでください:

  • プロジェクトがReact Router(react-router / Remix)を使用している場合。これは別のルーターであり、このスキルでは対応しません。
  • TanStack StartのSSR / サーバー関数 / ストリーミングデハイドレーションが必要な場合。Startは後段の利用側であり、ここでは扱いません。
  • ルーティングとは切り離されたTanStack Queryの仕組み(キャッシュ設定、ミューテーション、ルートに関係しない無限クエリ)が必要な場合。それはtanstack-queryスキルの役割です。このスキルでは、ルートローダー/コンテキスト経由で利用するクエリのみを扱います。

ワークフロー

ステップ1:バンドラープラグインをインストールして接続する
npm install @tanstack/react-router
npm install -D @tanstack/router-plugin                    # file-based routing (Vite/Rspack/Webpack)
npm install -D @tanstack/react-router-devtools            # optional, dev-only

Viteにプラグインを追加します。現在のエクスポート名は@tanstack/router-plugin/viteの**tanstackRouter(キャメルケース)です。@vitejs/plugin-reactより前に**実行する必要があります。

// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [
    tanstackRouter({ target: 'react', autoCodeSplitting: true }),
    react(),
  ],
})

このプラグインはsrc/routes/を監視し、src/routeTree.gen.tsを生成します。(従来のTanStackRouterViteという名前と@tanstack/router-vite-pluginパッケージもエイリアス経由で引き続き使用できますが、現在の名前はtanstackRouterです。references/sources.mdを参照してください。)

ステップ2:型安全なセットアップ(createRouter + RouterProvider + Register)

これは、アプリ全体のナビゲーションを型安全にするための接続です。Registerの宣言マージは必須です。これがないと、型付きフックがユニオン型にフォールバックし、オートコンプリートとコンパイル時チェックが失われます。

// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export const router = createRouter({
  routeTree,
  defaultPreload: 'intent',          // preload on hover/focus; see Step 6
  scrollRestoration: true,
})

// Declaration merging: binds YOUR router's type into the library's hooks.
declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}
// src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'
import { router } from './router'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)
ステップ3:ルートルート
// src/routes/__root.tsx
import { createRootRoute, Outlet, Link } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'

export const Route = createRootRoute({
  component: () => (
    <>
      <nav>
        <Link to="/">Home</Link>{' '}
        <Link to="/posts">Posts</Link>
      </nav>
      <Outlet />
      <TanStackRouterDevtools />
    </>
  ),
})

__root.tsxはすべてのルートをラップし、<Outlet />は一致した子ルートをレンダリングします。型付きルーターコンテキスト(たとえばqueryClientの注入)には、代わりにcreateRootRouteWithContext<T>()を使用してください。references/auth-and-testing.mdおよびreferences/query-integration.mdを参照してください。

ステップ 4:ルートを実装する — ファイルベース(推奨されるデフォルト)

ファイルベースルーティングは TanStack のデフォルトであり、ここでの基本的な方法です。ファイルの場所によって URL が決まります。createFileRoute('/path') は、最初にパス文字列を取り、次にオプションオブジェクトを取ります。パスパラメーター、検証済みの検索条件、ローダー、コンポーネントを備えた完全なルートの例です。

// src/routes/posts.$postId.tsx        ->  matches /posts/$postId
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
import { zodValidator } from '@tanstack/zod-adapter'

const postSearchSchema = z.object({
  tab: z.enum(['body', 'comments']).catch('body'),
})

export const Route = createFileRoute('/posts/$postId')({
  validateSearch: zodValidator(postSearchSchema),   // Zod v3 adapter; Zod v4: pass schema directly
  loader: async ({ params }) => fetchPost(params.postId),
  component: PostComponent,
})

function PostComponent() {
  const { postId } = Route.useParams()        // { postId: string } — typed
  const { tab } = Route.useSearch()           // { tab: 'body' | 'comments' } — typed
  const post = Route.useLoaderData()          // typed to the loader's return
  return <article data-tab={tab}>{post.title}</article>
}

Route.useParams()/Route.useSearch()/Route.useLoaderData() は、ファイル内で使用する型付きフックです。ルートオブジェクトがソースとなるため、from 引数は不要です。別のファイルから使用する場合は、useParams({ from: '/posts/$postId' }) または getRouteApi('/posts/$postId') を使います(references/search-and-loaders.md を参照)。

コードベースのルーティング(getParentRoute + addChildren + 手動の createRouter を使用する createRootRoute/createRoute)も完全にサポートされており、references/routing-approaches.md で一級の扱いを受けています。バンドラープラグインを実行できない場合に使用してください。

ステップ 5:ナビゲーションの基本
import { Link, useNavigate, redirect } from '@tanstack/react-router'

// Declarative — renders a real <a href>; preloads on intent.
<Link to="/posts/$postId" params={{ postId: '123' }} search={{ tab: 'comments' }}
      activeProps={{ className: 'active' }}>Post 123</Link>

// Imperative — for side effects (after a form submit, etc.).
const navigate = useNavigate()
navigate({ to: '/posts', search: (prev) => ({ ...prev, tab: 'body' }) })

// Redirect — THROW it from beforeLoad/loader (never navigate in a component for guards).
throw redirect({ to: '/login', search: { redirect: location.href } })

activeOptions、レンダープロップの isActive、ナビゲーションのブロック(useBlocker)、ルートマスキングを含む全機能については、references/navigation-and-splitting.md を参照してください。

ステップ 6:ローダーからデータへの連携(TanStack Query との連携)

ルートローダーはコンポーネントのレンダリング前に実行されるため、マウント時にはデータが揃っており、リンクへのインテントに応じて事前読み込みできます。TanStack Query との推奨される連携方法は、queryOptions ファクトリーを定義し、ローダー内で ensureQueryData を実行してから、コンポーネント内で useSuspenseQuery を使ってデータを読み取ることです。

import { createFileRoute } from '@tanstack/react-router'
import { useSuspenseQuery } from '@tanstack/react-query'
import { postQueryOptions } from '../queries'   // a queryOptions factory

export const Route = createFileRoute('/posts/$postId')({
  loader: ({ context: { queryClient }, params }) =>
    queryClient.ensureQueryData(postQueryOptions(params.postId)),
  component: Post,
})

function Post() {
  const { postId } = Route.useParams()
  const { data: post } = useSuspenseQuery(postQueryOptions(postId))  // cache hit — no refetch
  return <article>{post.title}</article>
}

queryClient はルーターコンテキスト(createRootRouteWithContext<{ queryClient: QueryClient }>() + createRouter({ context: { queryClient } }))を介してローダーに渡されます。全連携手順 — await と defer の使い分け、defaultPreloadStaleTime: 0、router.invalidate() を使った変更後の無効化、および公式の tanstack-query スキルへの相互参照 — は references/query-integration.md に記載されています。TanStack Query 自体の仕組み(クエリーキー、変更、一般的なキャッシュ調整)はここでは扱いません。それらについては tanstack-query スキルを参照してください。

ステップ 7:ルーティングされたコンポーネントをテストする

ブラウザーの URL を使わずにテスト対象のルートをレンダリングするには、メモリー内ルーターを構築し、RouterProvider でラップします。このスキルはこのテストハーネスを提供し、コンポーネントテストのスキルはこれを利用します。

import { render, screen } from '@testing-library/react'
import { createMemoryHistory, createRouter, RouterProvider, createRootRoute, createRoute } from '@tanstack/react-router'

function renderRoute(initialPath: string) {
  const rootRoute = createRootRoute()
  const indexRoute = createRoute({ getParentRoute: () => rootRoute, path: '/', component: HomePage })
  const routeTree = rootRoute.addChildren([indexRoute])
  const router = createRouter({
    routeTree,
    history: createMemoryHistory({ initialEntries: [initialPath] }),
  })
  render(<RouterProvider router={router} />)
}

ルーターは一致するコンポーネントが表示される前にローダーを解決するため、Testing Library の findBy* を使ってレンダリング結果を待ちます。router.navigate(...) でナビゲーションを実行します。型付きテストルーターファクトリー、ファイルベースツリーのバリアント、router.load() の待機を含むテストハーネス全体については、references/auth-and-testing.md を参照してください。

ルール

必ず守るルール(絶対に違反しないでください):

  • 必ず Register の宣言マージを追加してください。 declare module '@tanstack/react-router' { interface Register { router: typeof router } } がないと、型付きフックはすべてのルートのユニオン型に劣化し、コンパイル時のルートチェックができなくなります。
  • 認証/リダイレクトのガードは beforeLoad(または loader)に置き、コンポーネントには置かないでください。 beforeLoad から redirect(...) をスローすると、ルートはレンダリング前に停止します。コンポーネントでガードすると、保護されたコンテンツが先に一瞬表示されてしまいます。
  • ローダーが検索パラメーターに依存する場合は、必ず loaderDeps を使用してください。 依存関係を loaderDeps で宣言しない限り、検索条件が変わってもローダーは再実行されません。省略すると古いデータが返されます。
  • すべての検索パラメーターを validateSearch で検証してください。 検索パラメーターはユーザーが制御できる URL 入力です。検証せずに読み取ると、any の抜け穴が生じ、実行時のリスクになります。
  • 自身のルートファイル以外で型付きフックを使う場合は、from を渡すか、Route.*/getRouteApi を使用してください。 共通コンポーネントで引数なしの useParams() を使うと、そのルート固有の正確な型ではなくユニオン型が返されます。
  • クエリーの仕組みはルーティングを通じて扱ってください。 このスキルでは、TanStack Query はローダーとコンテキストの境界部分のみを対象とし、正規の参照先として tanstack-query を案内しています。スタンドアロンのクエリーパターンをルーターコードに持ち込まないでください。

推奨事項(必要に応じて変更できます):

  • ファイルベースのルーティング(tanstackRouter プラグインと createFileRoute)を優先してください。バンドラープラグインを実行できない場合に限り、コードベースのルーティングを使用してください。
  • ユーザーが開始するナビゲーションでは useNavigate より <Link> を優先してください(実際の <a href>、中クリック、プリロード、アクセシビリティに対応します)。useNavigate は副作用に限って使用してください。
  • スムーズなナビゲーションのために defaultPreload: 'intent' を設定してください。TanStack Query がキャッシュを管理する場合は、defaultPreloadStaleTime: 0 を設定してください。
  • 特別な理由がない限り、loader は初期バンドルに含めてください(コード分割しないでください)。コード分割すると、データを取得する前にサーバーとのラウンドトリップが追加されます。

注意点

  • TanStackRouterVite/@tanstack/router-vite-plugin は正しそうに見えますが、古い名前です。 現在のエクスポートは @tanstack/router-plugin/vite の tanstackRouter です。古い名前も引き続きエイリアスとして機能するため、コードは「動作」しますが、ドキュメントとのずれが生じます。現在の名前を使用してください。
  • routeTree.gen.ts は生成ファイルです。手動で編集してはいけません。また、createRouter より前に存在している必要があります。 ./routeTree.gen からのインポートに失敗する場合は、プラグインが実行されていない(開発サーバーを起動する/ビルドする)か、Vite の設定で react() より後に配置されています。
  • ローダーが気付かれないまま古いデータを返す場合、ほとんどの場合は loaderDeps の不足が原因です。 loaderDeps: ({ search }) => ({ page: search.page }) で依存関係を宣言しない限り、?page=2 に変更してもローダーは再実行されません。
  • 共通コンポーネントで useParams() の型が「壊れる」ことがあります。 from がないと、すべてのルートのパラメーターのユニオン型になります。from、Route.useParams()(同じファイル内)、または getRouteApi(path)(分割したファイル内)を使用してください。
  • Zod アダプターのバージョンに関する注意点。 Zod v3 では @tanstack/zod-adapter の zodValidator でラップしてください。Zod v4 ではアダプターは不要で、スキーマをそのまま validateSearch に渡します。古い @tanstack/router-zod-adapter パッケージは非推奨です。
  • 遅延データ:生のプロミスを返し、await しないでください。 現在のドキュメントでは、ローダーから 未 await の プロミスを返し、<Await>/useAwaited で受け取ります。スタンドアロンの defer() ヘルパーは主に SSR/ストリーミングのシリアライズ(Start)用で、SPA では必須ではありません。references/search-and-loaders.md を参照してください。
  • ローダーによるプリフェッチなしで useSuspenseQuery を使うと、初回描画時にサスペンドします。 ローダーで ensureQueryData を使うのは、コンポーネントの useSuspenseQuery でキャッシュヒットさせるためです。ローダーを省略すると、ローダーで解消するはずのウォーターフォールが再発します。

アンチパターン

  • 「ローダーではなく、useEffect 内でデータを取得します。」 これではレンダー後にデータを取得するウォーターフォールが再発し、プリロードが機能しなくなります。ローダーを使うことが重要です。
  • 「コンポーネント内でリダイレクトしてルートを保護します。」 保護されたコンテンツが一瞬表示され、レンダーも余分に発生します。beforeLoad で保護してください。
  • 「validateSearch は省略して、useSearch() の値をそのまま読み取ります。」 これは URL に由来する未検証の any です。URL の形式が不正だと、実行時エラーが発生します。
  • 「TanStack Query を統合するので、ここでキャッシュ/ミューテーション API 全体を説明します。」 範囲が逸脱しています。ルートを軸に説明し、詳細は tanstack-query を参照してください。
  • 「ルーターが対応しているので、TanStack Start の SSR/ストリーミングについても説明します。」 Start は別のプロダクト(後続の利用者)なので、対象外としてください。

出力

このスキルは、動作する TanStack Router のコードを生成します。内容は、vite.config.ts のプラグインエントリー、router.tsx(createRouter と Register)、RouterProvider の接続、ルートモジュール(ファイルベースを主とし、コードベースにも対応)、型付きナビゲーションとフック、検証済み検索パラメーター、TanStack Query に接続したローダー、メモリ履歴を使うテストハーネスです。想定する利用者は、React SPA でルーティングを構築するエンジニアまたはコーディングエージェントと、テストハーネスを再利用する関連コンポーネントテストのワークフローです。

関連項目

  • tanstack-query — TanStack Query の仕組み(クエリーキー、queryOptions、ミューテーション、キャッシュの調整)に関する正式な情報源です。このスキルではローダーとコンテキストの接点に関するすべてについてこれを参照し、内容を重複させません。
  • vite — @tanstack/router-plugin/vite プラグインを実行する開発サーバー兼バンドラーです。このプラグインが routeTree.gen.ts を生成します。
  • react-component-testing(関連スキル)— このスキルが提供するテストハーネス(Step 7/references/auth-and-testing.md)を利用します。
  • typescript-typecheck — Register の拡張と型付きフックは厳格な tsconfig を前提としています。ルートツリーの型チェックは tsc によって実行されます。
  • 境界(名前を挙げるだけで、説明はしない): TanStack Start(SSR/ストリーミング対応のフルスタックフレームワーク — 後続の利用者)、React Router(react-router/Remix — このスタックでは採用しない代替手段)。

段階的な開示

大量のコンテンツは references/ に格納されており、必要に応じて読み込みます。

  • references/routing-approaches.md — ルーティング構造を選択または実装する場合に読み込みます。完全なファイル命名規則の表(__root、index、$param、_pathless、(group)、$ スプラット、ドット記法、末尾のアンダースコアによるネスト解除)と、コードベースのアプローチ全体(createRoute + getParentRoute + addChildren + 手動の createRouter)、および用途の比較が含まれます。
  • references/search-and-loaders.md — 検索パラメーターとデータ読み込みを詳しく扱う場合に読み込みます。プラグイン可能なバリデーターを使った validateSearch(Zod アダプターの実例、Valibot/カスタム方式についての記載)、検索条件の読み取り/更新、親から子への継承、カスタムシリアライズ、検索ミドルウェア(retainSearchParams/stripSearchParams)、ローダー、loaderDeps、遅延データ(生の Promise + Await)、並列読み込み、コンテキストの読み込みを扱います。
  • references/navigation-and-splitting.md — ナビゲーションとバンドル処理を扱う場合に読み込みます。Link のオプション、useNavigate、redirect、useBlocker、コード分割(createLazyFileRoute/autoCodeSplitting)、プリロード(defaultPreload の値、preloadDelay、古さの判定時間)、スクロール復元、ルートマスキングを扱います。
  • references/auth-and-testing.md — 認証パターンまたはテストを扱う場合に読み込みます。createRootRouteWithContext、パスレスの _authenticated レイアウト、beforeLoad によるリダイレクトガード、notFound()、head/メタデータ、および完全なルーターのテストハーネス(メモリ履歴ファクトリー、ファイルベースツリーのバリエーション、ルーターの準備完了を待つ方法)が含まれます。
  • references/query-integration.md — TanStack Query との接続部分を扱う場合に読み込みます。ensureQueryData と useSuspenseQuery の連携、待機と遅延の選択、queryOptions ファクトリー、ミューテーション後の router.invalidate() による無効化、staleTime/gcTime/defaultPreloadStaleTime を扱います。すべてルーティングの観点から説明し、正式な tanstack-query スキルを相互参照します。
  • references/sources.md — 調査の出典情報(公式の tanstack.com/router ドキュメントページと、forge で確認済みの npm バージョン)です。

このスキルには scripts/ や assets/ は含まれません。

本文の上限

  • description は 1,024 文字以下です(遵守済み)。
  • 本文は約 500 行/5,000 トークン以下です。毎ターンのコンテキストに保持し、長い内容は references/ に置いています。
  • 各リファレンスファイルは、10k トークン超で警告、25k トークン超でエラーになります。リファレンス全体は、25k トークン超で警告、50k トークン超でエラーになります。

コメント