mcpField
P
path-params

path-params

github.com/tanstack開発15.3k197 回インストール4 日前に更新
リポジトリ

path-params について

TanStack Router 開発者向けのスキルです。動的、任意、キャッチオール、パターン付き URL パラメーターを説明し、型推論を活用したルート定義と安全な遷移に役立ちます。

主な機能

  1. 01動的および複数のパスパラメーター
  2. 02キャッチオールと任意パラメーター
  3. 03接頭辞・接尾辞付きパターン
  4. 04型付きパラメーターの参照と推論
  5. 05安全な遷移とエンコード

活用シーン

  1. 01リソース ID から詳細ルートを構築
  2. 02キャッチオールのファイルルートを作成
  3. 03任意のロケールやカテゴリのパスに対応
  4. 04型付きパラメーターを保って遷移

インストール

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

$npx skills add https://github.com/tanstack/router --skill path-params

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

詳細

パスパラメーター

パスパラメーターは、動的な URL セグメントを名前付き変数に格納します。ルートパス内で $ を接頭辞として付けて定義します。

CRITICAL:パラメーターを to 文字列に直接埋め込まないでください。必ず params プロパティを使用してください。これは、パスパラメーターに関してエージェントが最もよく起こす間違いです。

CRITICAL:型はすべて推論されます。useParams() の戻り値に型注釈を付けないでください。

動的セグメント

$ を接頭辞として付けたセグメントは、次の / までのテキストを取得します。

// src/routes/posts.$postId.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params }) => {
    // params.postId is string — fully inferred, do not annotate
    return fetchPost(params.postId)
  },
  component: PostComponent,
})

function PostComponent() {
  const { postId } = Route.useParams()
  const data = Route.useLoaderData()
  return (
    <h1>
      Post {postId}: {data.title}
    </h1>
  )
}

複数の動的セグメントを異なるパス階層で使用できます。

// src/routes/teams.$teamId.members.$memberId.tsx
export const Route = createFileRoute('/teams/$teamId/members/$memberId')({
  component: MemberComponent,
})

function MemberComponent() {
  const { teamId, memberId } = Route.useParams()
  return (
    <div>
      Team {teamId}, Member {memberId}
    </div>
  )
}

スプラット/キャッチオールルート

パスの末尾が $(ドル記号のみ)のルートは、その後に続くすべての内容を取得します。値は _splat キーから取得できます。

// src/routes/files.$.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/files/$')({
  component: FileViewer,
})

function FileViewer() {
  const { _splat } = Route.useParams()
  // URL: /files/documents/report.pdf → _splat = "documents/report.pdf"
  return <div>File path: {_splat}</div>
}

オプションパラメーター

オプションパラメーターには {-$paramName} 構文を使用します。このセグメントは存在する場合としない場合があります。存在しない場合、値は undefined になります。

// src/routes/posts.{-$category}.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/{-$category}')({
  component: PostsComponent,
})

function PostsComponent() {
  const { category } = Route.useParams()
  // URL: /posts → category is undefined
  // URL: /posts/tech → category is "tech"
  return <div>{category ? `Posts in ${category}` : 'All Posts'}</div>
}

複数のオプションパラメーター:

// Matches: /posts, /posts/tech, /posts/tech/hello-world
export const Route = createFileRoute('/posts/{-$category}/{-$slug}')({
  component: PostComponent,
})
オプションのロケールによる i18n
// src/routes/{-$locale}/about.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/{-$locale}/about')({
  component: AboutComponent,
})

function AboutComponent() {
  const { locale } = Route.useParams()
  const currentLocale = locale || 'en'
  return <h1>{currentLocale === 'fr' ? 'À Propos' : 'About Us'}</h1>
}
// Matches: /about, /en/about, /fr/about

接頭辞と接尾辞のパターン

$paramName の前後を波括弧 {} で囲むと、1 つのセグメント内で動的な部分の前後にテキストを追加できます。

接頭辞
// src/routes/posts/post-{$postId}.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/post-{$postId}')({
  component: PostComponent,
})

function PostComponent() {
  const { postId } = Route.useParams()
  // URL: /posts/post-123 → postId = "123"
  return <div>Post ID: {postId}</div>
}
接尾辞
// src/routes/files/{$fileName}[.]txt.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/files/{$fileName}.txt')({
  component: FileComponent,
})

function FileComponent() {
  const { fileName } = Route.useParams()
  // URL: /files/readme.txt → fileName = "readme"
  return <div>File: {fileName}.txt</div>
}
接頭辞と接尾辞の組み合わせ
// URL: /users/user-456.json → userId = "456"
export const Route = createFileRoute('/users/user-{$userId}.json')({
  component: UserComponent,
})

function UserComponent() {
  const { userId } = Route.useParams()
  return <div>User: {userId}</div>
}

パスパラメーターを使ったナビゲーション

オブジェクト形式
import { Link } from '@tanstack/react-router'

function PostLink({ postId }: { postId: string }) {
  return (
    <Link to="/posts/$postId" params={{ postId }}>
      View Post
    </Link>
  )
}
関数形式(その他のパラメーターを保持)
function PostLink({ postId }: { postId: string }) {
  return (
    <Link to="/posts/$postId" params={(prev) => ({ ...prev, postId })}>
      View Post
    </Link>
  )
}
プログラムによるナビゲーション
import { useNavigate } from '@tanstack/react-router'

function GoToPost({ postId }: { postId: string }) {
  const navigate = useNavigate()

  return (
    <button
      onClick={() => {
        navigate({ to: '/posts/$postId', params: { postId } })
      }}
    >
      Go to Post
    </button>
  )
}
オプションパラメーターを使ったナビゲーション
// Include the optional param
<Link to="/posts/{-$category}" params={{ category: 'tech' }}>
  Tech Posts
</Link>

// Omit the optional param (renders /posts)
<Link to="/posts/{-$category}" params={{ category: undefined }}>
  All Posts
</Link>

ルートコンポーネント外でパラメーターを読み取る

from を指定した useParams
import { useParams } from '@tanstack/react-router'

function PostHeader() {
  const { postId } = useParams({ from: '/posts/$postId' })
  return <h2>Post {postId}</h2>
}
strict: false を指定した useParams
function GenericBreadcrumb() {
  const params = useParams({ strict: false })
  // params is a union of all possible route params
  return <span>{params.postId ?? 'Home'}</span>
}

ローダーと beforeLoad のパラメーター

export const Route = createFileRoute('/posts/$postId')({
  beforeLoad: async ({ params }) => {
    // params.postId available here
    const canView = await checkPermission(params.postId)
    if (!canView) throw redirect({ to: '/unauthorized' })
  },
  loader: async ({ params }) => {
    return fetchPost(params.postId)
  },
})

使用可能な文字

デフォルトでは、パラメーターは encodeURIComponent でエンコードされます。ルーターの設定で、追加の文字を許可できます。

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

const router = createRouter({
  routeTree,
  pathParamsAllowedCharacters: ['@', '+'],
})

使用可能な文字:;、: 、@、&、=、+、$、,。

よくある間違い

1. CRITICAL(スキル横断):パスパラメーターを to 文字列に直接埋め込む
// WRONG — breaks type safety and param encoding
<Link to={`/posts/${postId}`}>Post</Link>

// CORRECT — use params prop
<Link to="/posts/$postId" params={{ postId }}>Post</Link>
2. MEDIUM:スプラットルートに $ ではなく * を使う

TanStack Router では、スプラットルートに $ を使用します。取得した値は * ではなく _splat に格納されます。

// WRONG (React Router / other frameworks)
// <Route path="/files/*" />

// CORRECT (TanStack Router)
// File: src/routes/files.$.tsx
export const Route = createFileRoute('/files/$')({
  component: () => {
    const { _splat } = Route.useParams()
    return <div>{_splat}</div>
  },
})

注:* は後方互換性のため v1 では機能しますが、v2 で削除される予定です。必ず _splat を使用してください。

3. MEDIUM:基本的な動的セグメントに波括弧を使う

波括弧は、接頭辞/接尾辞のパターンとオプションパラメーターにのみ使用します。基本的な動的セグメントには、波括弧を付けずに $ を使用します。

// WRONG — braces not needed for basic params
createFileRoute('/posts/{$postId}')

// CORRECT — bare $ for basic dynamic segments
createFileRoute('/posts/$postId')

// CORRECT — braces for prefix pattern
createFileRoute('/posts/post-{$postId}')

// CORRECT — braces for optional param
createFileRoute('/posts/{-$category}')
4. パラメーターは常に文字列

パスパラメーターは常に文字列として解析されます。数値が必要な場合は、ローダーまたはコンポーネントで解析してください。

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params }) => {
    const id = parseInt(params.postId, 10)
    if (isNaN(id)) throw notFound()
    return fetchPost(id)
  },
})

双方向変換を行うには、ルートで params.parse と params.stringify を使用することもできます。

export const Route = createFileRoute('/posts/$postId')({
  params: {
    parse: (raw) => ({ postId: parseInt(raw.postId, 10) }),
    stringify: (parsed) => ({ postId: String(parsed.postId) }),
  },
  loader: async ({ params }) => {
    // params.postId is now number
    return fetchPost(params.postId)
  },
})

コメント