#Generated + Dynamic Page

1 messages · Page 1 of 1 (latest)

acoustic snow
#

In nextjs 14 app dir.. i have this dynamic route with the following code

export const dynamic = 'force-dynamic'

export async function generateStaticParams() {
  const payload = await getPayload({ config: configPromise })
  const posts = await payload.find({
    collection: 'articles',
    draft: false,
    limit: 1000,
    overrideAccess: false,
    pagination: false,
    select: {
      slug: true,
    },
  })

  const params = posts.docs.map(({ slug }) => {
    return { slug }
  })

  return params
}

type Args = {
  params: Promise<{
    category: string
    slug: string
  }>
}

export default async function Post({ params }: Args) {
  const { isEnabled: draft } = await draftMode()
  const { category, slug } = await params

  const headers = await headerPromise()
  const post = await queryPostBySlug({ headers, slug })

  if (!post) {
    notFound()
  }
  console.log(post.title)
  return (
    
  )
}

const queryPostBySlug = cache(
  async ({ headers: passedHeaders, slug }: { headers?: ReadonlyHeaders; slug: string }) => {
    const { isEnabled: draft } = await draftMode()

    const payload = await getPayload({ config: configPromise })
    let userIP = '0.0.0.0'
    if (passedHeaders) {
      userIP =
        passedHeaders?.get('x-real-ip') ||
        passedHeaders?.get('cf-connecting-ip') ||
        passedHeaders?.get('x-client-ip') ||
        '0.0.0.0'
    }

    const result = await payload.find({
      collection: 'articles',
      draft,
      limit: 1,
      overrideAccess: draft,
      pagination: false,
      where: {
        slug: {
          equals: slug,
        },
      },
      ...(passedHeaders &&
        !draft && {
          req: {
            headers: {
              ...passedHeaders,
              'x-site-forwarded-ip': userIP,
            } as unknown as Headers,
          },
        }),
    })

    return result.docs?.[0] || null
  },
)

Now why does this page still act as SSG. I am getting DYANMIC_SERVER errors

fading pecanBOT
#

Hi @acoustic snow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

I understand your confusion about why your page is still being treated as a static page despite using export const dynamic = 'force-dynamic'. Let's look at what's happening based on the knowledge sources.

The Issue with force-dynamic and generateStaticParams

You're experiencing a conflict between two different configurations:

  1. export const dynamic = 'force-dynamic' - This tells Next.js to render the page dynamically on every request
  2. export async function generateStaticParams() - This is used for static site generation (SSG)

These two directives are contradicting each other. When you use both together, Next.js gets confused about how to handle the page.

According to this issue, there's a known problem where the route segment config (like force-dynamic) isn't always respected for imported server actions. This could be related to your issue.

Why You're Getting DYNAMIC_SERVER Errors

The error you're seeing is likely because Next.js is trying to statically generate your page during build time (because of generateStaticParams), but then encounters dynamic server usage (from force-dynamic).

As mentioned in this issue, this can lead to errors like:

error: Static generation failed due to dynamic usage on /dashboard/promos, reason: Dynamic server usage: Page with `dynamic = "force-dynamic"` won't be rendered statically.

Solutions

You have a few options:

  1. Remove generateStaticParams if you truly want dynamic rendering:
    If you need the page to be fully dynamic and rendered on each request, you should remove the generateStaticParams function.
#
  1. Remove force-dynamic if you want static generation with dynamic paths:
    If you want to pre-render specific paths at build time, keep generateStaticParams but remove force-dynamic.

  2. Use ISR (Incremental Static Regeneration) instead:
    If you want a mix of static generation with periodic updates, use revalidate instead of force-dynamic:

    export const revalidate = 60; // revalidate every 60 seconds
    
  3. Use dynamicParams option:
    If you want to control how non-generated paths are handled:

    export const dynamicParams = true; // allow dynamic params that aren't generated
    

According to this issue, using both output: 'export' and route segment configs like dynamic and dynamicParams together can cause issues in development mode.

Conclusion

The core issue is that you're mixing static generation directives (generateStaticParams) with dynamic rendering directives (force-dynamic), which are fundamentally at odds with each other. Choose one approach based on your actual requirements for the page.

I hope this helps clarify why you're experiencing this issue!

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@acoustic snow Kapa.ai is still learning and improving, please let me know how I did by reacting below.

acoustic snow
#

whats the thing to generate multiple urls of a dynamic segment on build time @fading pecan

fading pecanBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Based on your question about generating multiple URLs for a dynamic segment at build time in Next.js, you're looking for the generateStaticParams function.

generateStaticParams is used with dynamic route segments to statically generate routes at build time instead of on-demand at request time. This is the App Router equivalent of getStaticPaths from the Pages Router.

Here's how you can use it:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  // Fetch data from an API or database
  const posts = await fetch('<https://.../posts'>).then((res) => res.json())
 
  // Return an array of objects, each containing the params for a route
  return posts.map((post) => ({
    slug: post.slug,
  }))
}

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

For routes with multiple dynamic segments, you can return objects with multiple properties:

// app/products/[category]/[product]/page.tsx
export function generateStaticParams() {
  return [
    { category: 'a', product: '1' },
    { category: 'b', product: '2' },
    { category: 'c', product: '3' },
  ]
}

For catch-all routes like [...slug]:

// app/product/[...slug]/page.tsx
export function generateStaticParams() {
  return [
    { slug: ['a', '1'] }, 
    { slug: ['b', '2'] }, 
    { slug: ['c', '3'] }
  ]
}

The primary benefit of generateStaticParams is that data fetching is automatically memoized, which improves build performance when fetching the same data in multiple components.

Learn more about generateStaticParams

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: