mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
327 lines
10 KiB
Plaintext
327 lines
10 KiB
Plaintext
---
|
|
title: generateStaticParams
|
|
description: API reference for the generateStaticParams function.
|
|
---
|
|
|
|
The `generateStaticParams` function can be used in combination with [dynamic route segments](/docs/app/building-your-application/routing/dynamic-routes) to [**statically generate**](/docs/app/building-your-application/rendering/server-components#static-rendering-default) routes at build time instead of on-demand at request time.
|
|
|
|
```jsx filename="app/blog/[slug]/page.js"
|
|
// Return a list of `params` to populate the [slug] dynamic segment
|
|
export async function generateStaticParams() {
|
|
const posts = await fetch('https://.../posts').then((res) => res.json())
|
|
|
|
return posts.map((post) => ({
|
|
slug: post.slug,
|
|
}))
|
|
}
|
|
|
|
// Multiple versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
export default function Page({ params }) {
|
|
const { slug } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
> **Good to know**
|
|
>
|
|
> - You can use the [`dynamicParams`](/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams) segment config option to control what happens when a dynamic segment is visited that was not generated with `generateStaticParams`.
|
|
> - During `next dev`, `generateStaticParams` will be called when you navigate to a route.
|
|
> - During `next build`, `generateStaticParams` runs before the corresponding Layouts or Pages are generated.
|
|
> - During revalidation (ISR), `generateStaticParams` will not be called again.
|
|
> - `generateStaticParams` replaces the [`getStaticPaths`](/docs/pages/api-reference/functions/get-static-paths) function in the Pages Router.
|
|
|
|
## Parameters
|
|
|
|
`options.params` (optional)
|
|
|
|
If multiple dynamic segments in a route use `generateStaticParams`, the child `generateStaticParams` function is executed once for each set of `params` the parent generates.
|
|
|
|
The `params` object contains the populated `params` from the parent `generateStaticParams`, which can be used to [generate the `params` in a child segment](#multiple-dynamic-segments-in-a-route).
|
|
|
|
## Returns
|
|
|
|
`generateStaticParams` should return an array of objects where each object represents the populated dynamic segments of a single route.
|
|
|
|
- Each property in the object is a dynamic segment to be filled in for the route.
|
|
- The properties name is the segment's name, and the properties value is what that segment should be filled in with.
|
|
|
|
| Example Route | `generateStaticParams` Return Type |
|
|
| -------------------------------- | ----------------------------------------- |
|
|
| `/product/[id]` | `{ id: string }[]` |
|
|
| `/products/[category]/[product]` | `{ category: string, product: string }[]` |
|
|
| `/products/[...slug]` | `{ slug: string[] }[]` |
|
|
|
|
## Single Dynamic Segment
|
|
|
|
```tsx filename="app/product/[id]/page.tsx" switcher
|
|
export function generateStaticParams() {
|
|
return [{ id: '1' }, { id: '2' }, { id: '3' }]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /product/1
|
|
// - /product/2
|
|
// - /product/3
|
|
export default function Page({ params }: { params: { id: string } }) {
|
|
const { id } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/product/[id]/page.js" switcher
|
|
export function generateStaticParams() {
|
|
return [{ id: '1' }, { id: '2' }, { id: '3' }]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /product/1
|
|
// - /product/2
|
|
// - /product/3
|
|
export default function Page({ params }) {
|
|
const { id } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
## Multiple Dynamic Segments
|
|
|
|
```tsx filename="app/products/[category]/[product]/page.tsx" switcher
|
|
export function generateStaticParams() {
|
|
return [
|
|
{ category: 'a', product: '1' },
|
|
{ category: 'b', product: '2' },
|
|
{ category: 'c', product: '3' },
|
|
]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /products/a/1
|
|
// - /products/b/2
|
|
// - /products/c/3
|
|
export default function Page({
|
|
params,
|
|
}: {
|
|
params: { category: string; product: string }
|
|
}) {
|
|
const { category, product } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/products/[category]/[product]/page.js" switcher
|
|
export function generateStaticParams() {
|
|
return [
|
|
{ category: 'a', product: '1' },
|
|
{ category: 'b', product: '2' },
|
|
{ category: 'c', product: '3' },
|
|
]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /products/a/1
|
|
// - /products/b/2
|
|
// - /products/c/3
|
|
export default function Page({ params }) {
|
|
const { category, product } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
## Catch-all Dynamic Segment
|
|
|
|
```tsx filename="app/product/[...slug]/page.tsx" switcher
|
|
export function generateStaticParams() {
|
|
return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /product/a/1
|
|
// - /product/b/2
|
|
// - /product/c/3
|
|
export default function Page({ params }: { params: { slug: string[] } }) {
|
|
const { slug } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/product/[...slug]/page.js" switcher
|
|
export function generateStaticParams() {
|
|
return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
|
|
}
|
|
|
|
// Three versions of this page will be statically generated
|
|
// using the `params` returned by `generateStaticParams`
|
|
// - /product/a/1
|
|
// - /product/b/2
|
|
// - /product/c/3
|
|
export default function Page({ params }) {
|
|
const { slug } = params
|
|
// ...
|
|
}
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Multiple Dynamic Segments in a Route
|
|
|
|
You can generate params for dynamic segments above the current layout or page, but **not below**. For example, given the `app/products/[category]/[product]` route:
|
|
|
|
- `app/products/[category]/[product]/page.js` can generate params for **both** `[category]` and `[product]`.
|
|
- `app/products/[category]/layout.js` can **only** generate params for `[category]`.
|
|
|
|
There are two approaches to generating params for a route with multiple dynamic segments:
|
|
|
|
### Generate params from the bottom up
|
|
|
|
Generate multiple dynamic segments from the child route segment.
|
|
|
|
```tsx filename="app/products/[category]/[product]/page.tsx" switcher
|
|
// Generate segments for both [category] and [product]
|
|
export async function generateStaticParams() {
|
|
const products = await fetch('https://.../products').then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
category: product.category.slug,
|
|
product: product.id,
|
|
}))
|
|
}
|
|
|
|
export default function Page({
|
|
params,
|
|
}: {
|
|
params: { category: string; product: string }
|
|
}) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/products/[category]/[product]/page.js" switcher
|
|
// Generate segments for both [category] and [product]
|
|
export async function generateStaticParams() {
|
|
const products = await fetch('https://.../products').then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
category: product.category.slug,
|
|
product: product.id,
|
|
}))
|
|
}
|
|
|
|
export default function Page({ params }) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### Generate params from the top down
|
|
|
|
Generate the parent segments first and use the result to generate the child segments.
|
|
|
|
```tsx filename="app/products/[category]/layout.tsx" switcher
|
|
// Generate segments for [category]
|
|
export async function generateStaticParams() {
|
|
const products = await fetch('https://.../products').then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
category: product.category.slug,
|
|
}))
|
|
}
|
|
|
|
export default function Layout({ params }: { params: { category: string } }) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/products/[category]/layout.js" switcher
|
|
// Generate segments for [category]
|
|
export async function generateStaticParams() {
|
|
const products = await fetch('https://.../products').then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
category: product.category.slug,
|
|
}))
|
|
}
|
|
|
|
export default function Layout({ params }) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
A child route segment's `generateStaticParams` function is executed once for each segment a parent `generateStaticParams` generates.
|
|
|
|
The child `generateStaticParams` function can use the `params` returned from the parent `generateStaticParams` function to dynamically generate its own segments.
|
|
|
|
```tsx filename="app/products/[category]/[product]/page.tsx" switcher
|
|
// Generate segments for [product] using the `params` passed from
|
|
// the parent segment's `generateStaticParams` function
|
|
export async function generateStaticParams({
|
|
params: { category },
|
|
}: {
|
|
params: { category: string }
|
|
}) {
|
|
const products = await fetch(
|
|
`https://.../products?category=${category}`
|
|
).then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
product: product.id,
|
|
}))
|
|
}
|
|
|
|
export default function Page({
|
|
params,
|
|
}: {
|
|
params: { category: string; product: string }
|
|
}) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/products/[category]/[product]/page.js" switcher
|
|
// Generate segments for [product] using the `params` passed from
|
|
// the parent segment's `generateStaticParams` function
|
|
export async function generateStaticParams({ params: { category } }) {
|
|
const products = await fetch(
|
|
`https://.../products?category=${category}`
|
|
).then((res) => res.json())
|
|
|
|
return products.map((product) => ({
|
|
product: product.id,
|
|
}))
|
|
}
|
|
|
|
export default function Page({ params }) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
> **Good to know**: `fetch` requests are automatically [memoized](/docs/app/building-your-application/caching#request-memoization) for the same data across all `generate`-prefixed functions, Layouts, Pages, and Server Components. React [`cache` can be used](/docs/app/building-your-application/caching#request-memoization) if `fetch` is unavailable.
|
|
|
|
### Generate only a subset of params
|
|
|
|
You can generate a subset of params for a route by returning an array of objects with only the dynamic segments you want to generate. Then, by using the [`dynamicParams`](/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams) segment config option, you can control what happens when a dynamic segment is visited that was not generated with `generateStaticParams`.
|
|
|
|
```jsx filename="app/blog/[slug]/page.js"
|
|
// All posts besides the top 10 will be a 404
|
|
export const dynamicParams = false
|
|
|
|
export async function generateStaticParams() {
|
|
const posts = await fetch('https://.../posts').then((res) => res.json())
|
|
const topPosts = posts.slice(0, 10)
|
|
|
|
return topPosts.map((post) => ({
|
|
slug: post.slug,
|
|
}))
|
|
}
|
|
```
|
|
|
|
## Version History
|
|
|
|
| Version | Changes |
|
|
| --------- | ---------------------------------- |
|
|
| `v13.0.0` | `generateStaticParams` introduced. |
|