動態路由區段

當您無法預先知道確切的路由區段名稱,並希望根據動態資料建立路由時,可以使用動態區段,這些區段會在請求時填充或在建置時預先渲染。

慣例

動態區段可透過將資料夾名稱用方括號包裹來建立:[folderName]。例如,一個部落格可能包含以下路由 app/blog/[slug]/page.js,其中 [slug] 是部落格文章的動態區段。

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params
  return <div>My Post: {slug}</div>
}

動態區段會作為 params 屬性傳遞給 layoutpageroutegenerateMetadata 函數。

路由範例 URLparams
app/blog/[slug]/page.js/blog/a{ slug: 'a' }
app/blog/[slug]/page.js/blog/b{ slug: 'b' }
app/blog/[slug]/page.js/blog/c{ slug: 'c' }

萬用區段

動態區段可透過在括號內添加省略號 [...folderName] 來擴展為萬用後續區段。

例如,app/shop/[...slug]/page.js 會匹配 /shop/clothes,也會匹配 /shop/clothes/tops/shop/clothes/tops/t-shirts 等。

路由範例 URLparams
app/shop/[...slug]/page.js/shop/a{ slug: ['a'] }
app/shop/[...slug]/page.js/shop/a/b{ slug: ['a', 'b'] }
app/shop/[...slug]/page.js/shop/a/b/c{ slug: ['a', 'b', 'c'] }

可選萬用區段

萬用區段可透過將參數放在雙層方括號中 [[...folderName]] 來設為可選

例如,app/shop/[[...slug]]/page.js 除了會匹配 /shop/clothes/shop/clothes/tops/shop/clothes/tops/t-shirts 外,還會匹配 /shop

萬用可選萬用區段的區別在於,可選萬用區段也會匹配不帶參數的路由(如上例中的 /shop)。

路由範例 URLparams
app/shop/[[...slug]]/page.js/shop{ slug: undefined }
app/shop/[[...slug]]/page.js/shop/a{ slug: ['a'] }
app/shop/[[...slug]]/page.js/shop/a/b{ slug: ['a', 'b'] }
app/shop/[[...slug]]/page.js/shop/a/b/c{ slug: ['a', 'b', 'c'] }

TypeScript

使用 TypeScript 時,您可以根據配置的路由區段為 params 添加類型。

路由params 類型定義
app/blog/[slug]/page.js{ slug: string }
app/shop/[...slug]/page.js{ slug: string[] }
app/shop/[[...slug]]/page.js{ slug?: string[] }
app/[categoryId]/[itemId]/page.js{ categoryId: string, itemId: string }

行為

  • 由於 params 屬性是一個 Promise,您必須使用 async/await 或 React 的 use 函數來存取其值。
    • 在版本 14 及更早版本中,params 是一個同步屬性。為了向後兼容,在 Next.js 15 中您仍可以同步存取它,但此行為在未來將會被棄用。

範例

使用 generateStaticParams

generateStaticParams 函數可用於在建置時靜態生成路由,而非在請求時按需生成。

export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

generateStaticParams 函數中使用 fetch 時,請求會自動去重。這避免了對相同資料進行多次網路請求(包括 Layouts、Pages 和其他 generateStaticParams 函數),從而加快建置速度。

On this page