路徑參數 (Path Params) 用於匹配單一區段 (直到下一個 / 前的文字),並將其值作為命名變數回傳。它們透過在路徑中使用 $ 字元前綴來定義,後接要賦值的鍵值變數。以下是有效的路徑參數範例:
由於路徑參數路由僅匹配到下一個 /,因此可以建立子路由來延續層級結構:
讓我們建立一個使用路徑參數匹配文章 ID 的文章路由檔案:
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
一旦路徑參數被解析,所有子路由都可以使用它。這表示如果我們為 postRoute 定義子路由,就能在子路由路徑中使用來自 URL 的 postId 變數!
路徑參數會以 params 物件形式傳遞給載入器。此物件的鍵是路徑參數的名稱,值則是從實際 URL 路徑解析出的數值。例如,如果我們訪問 /blog/123 URL,params 物件會是 { postId: '123' }:
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
params 物件也會傳遞給 beforeLoad 選項:
export const Route = createFileRoute('/posts/$postId')({
beforeLoad: async ({ params }) => {
// 使用 params.postId 進行操作
},
})
export const Route = createFileRoute('/posts/$postId')({
beforeLoad: async ({ params }) => {
// 使用 params.postId 進行操作
},
})
如果我們在 postRoute 中加入元件,可以透過路由的 useParams 鉤子 (hook) 從 URL 存取 postId 變數:
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post {postId}</div>
}
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post {postId}</div>
}
🧠 小技巧:如果元件採用程式碼分割 (code-split),可以使用 getRouteApi 函式 來避免匯入 Route 設定,同時仍能存取型別化的 useParams() 鉤子。
你也可以使用全域匯出的 useParams 鉤子,從應用程式的任何元件存取已解析的路徑參數。需傳遞 strict: false 選項給 useParams,表示要從不明確的位置存取參數:
function PostComponent() {
const { postId } = useParams({ strict: false })
return <div>Post {postId}</div>
}
function PostComponent() {
const { postId } = useParams({ strict: false })
return <div>Post {postId}</div>
}
導航至含有路徑參數的路由時,TypeScript 會要求你以物件形式或函式形式傳遞參數。以下是物件形式的範例:
function Component() {
return (
<Link to="/blog/$postId" params={{ postId: '123' }}>
Post 123
</Link>
)
}
function Component() {
return (
<Link to="/blog/$postId" params={{ postId: '123' }}>
Post 123
</Link>
)
}
以下是函式形式的範例:
function Component() {
return (
<Link to="/blog/$postId" params={(prev) => ({ ...prev, postId: '123' })}>
Post 123
</Link>
)
}
function Component() {
return (
<Link to="/blog/$postId" params={(prev) => ({ ...prev, postId: '123' })}>
Post 123
</Link>
)
}
注意,函式形式在需要保留 URL 中其他路由的現有參數時特別有用。這是因為函式形式會接收當前參數作為引數,讓你能視需要修改後回傳最終的參數物件。
預設情況下,路徑參數會透過 encodeURIComponent 進行跳脫。如果想允許其他有效的 URI 字元 (例如 @ 或 +),可以在 RouterOptions 中指定。
使用範例:
const router = createRouter({
...
pathParamsAllowedCharacters: ['@']
})
const router = createRouter({
...
pathParamsAllowedCharacters: ['@']
})
以下是可接受的允許字元清單: ; : @ & = + $ ,
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.