Sử dụng generateStaticParams ở đây có tác dụng gì? 😒

Trong file này, hàm generateStaticParams có tác dụng như sau:generateStaticParams là một hàm đặc biệt trong Next.js (App Router) dùng để xác định trước các route động (dynamic routes) sẽ được tạo ra ở thời điểm build (tức là static generation).Cụ thể ở đây:

  • Đường dẫn của bạn là /blog/[slug], tức là mỗi bài viết sẽ có một slug khác nhau.

  • generateStaticParams sẽ lấy tất cả các bài viết (bằng getAllPosts), sau đó trả về một mảng các object dạng { slug: post.slug }.

  • Next.js sẽ dùng mảng này để biết cần phải build sẵn những trang nào cho từng slug cụ thể.

Ví dụ: Nếu bạn có 3 bài viết với slug là "hello-world", "nextjs-tutorial", "react-hooks", thì generateStaticParams sẽ trả về:

[
  { slug: "hello-world" },
  { slug: "nextjs-tutorial" },
  { slug: "react-hooks" }
]

Kết quả: Next.js sẽ tạo sẵn (pre-render) các trang /blog/hello-world, /blog/nextjs-tutorial, /blog/react-hooks ở thời điểm build, giúp các trang này load rất nhanh và thân thiện SEO. Tóm lại: generateStaticParams giúp Next.js biết trước những giá trị slug nào sẽ có để tạo sẵn các trang tương ứng cho route động [slug]. Nếu không có hàm này, Next.js sẽ không biết cần build sẵn những trang nào cho route động đó.

src\app\blog\[slug]\page.tsx

import getAllPosts from '@/lib/queries/getAllPosts'
import getPostBySlug from '@/lib/queries/getPostBySlug'
import type {DynamicPageProps} from '@/lib/types'
import {Metadata} from 'next'
import Image from 'next/image'
import Link from 'next/link'
import {notFound} from 'next/navigation'
/**
 * Generate the static routes at build time.
 *
 * @see https://nextjs.org/docs/app/api-reference/functions/generate-static-params
 */
export async function generateStaticParams() {
  // Get all blog posts.
  const posts = await getAllPosts();
  // No posts? Bail...
  if (!posts) {
    return []
  }
  // Return the slugs for each post.
  return posts.map((post: {slug: string}) => ({
    slug: post.slug
  }))
}
/**
 * Generate the metadata for each static route at build time.
 *
 * @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function
 */
export async function generateMetadata({
  params
}: DynamicPageProps): Promise<Metadata | null> {
  // Get the slug from the params.
  const {slug} = await params
  // Get the blog post.
  const post = await getPostBySlug(slug)
  // No post? Bail...
  if (!post) {
    return {}
  }
  return {
    title: post.seo.title,
    description: post.seo.metaDesc
  }
}
/**
 * The blog post route.
 *
 * @see https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#pages
 */
export default async function Post({params}: Readonly<DynamicPageProps>) {
  // Get the slug from the params.
  const {slug} = await params
  // Fetch a single post from WordPress.
  const post = await getPostBySlug(slug)
  // No post? Bail...
  if (!post) {
    notFound()
  }
  return (
    <article>
      <header>
        <h2 dangerouslySetInnerHTML={{__html: post.title}} />
        <p className="italic">
          By {post.author.node.name} on <time>{post.date}</time>
        </p>
      </header>
      <div dangerouslySetInnerHTML={{__html: post.content}} />
      <footer className="flex items-center justify-between gap-4 pb-4">
        <div>
          <h3>Categories</h3>
          <ul className="m-0 flex list-none gap-2 p-0">
            {post.categories.nodes.map((category) => (
              <li className="m-0 p-0" key={category.databaseId}>
                <Link href={`/blog/category/${category.name}`}>
                  {category.name}
                </Link>
              </li>
            ))}
          </ul>
        </div>
        <div>
          <h3>Tags</h3>
          <ul className="m-0 flex list-none gap-2 p-0">
            {post.tags.nodes.map((tag) => (
              <li className="m-0 p-0" key={tag.databaseId}>
                <Link href={`/blog/tag/${tag.name}`}>{tag.name}</Link>
              </li>
            ))}
          </ul>
        </div>
      </footer>
      <section className="border-t-2">
        <h3>Comments</h3>
        {post.comments.nodes.map((comment) => (
          <article key={comment.databaseId}>
            <header className="flex items-center gap-2">
              <Image
                alt={comment.author.node.name}
                className="m-0 rounded-full"
                height={64}
                loading="lazy"
                src={comment.author.node.avatar.url}
                width={64}
              />
              <div className="flex flex-col gap-2">
                <h4
                  className="m-0 p-0 leading-none"
                  dangerouslySetInnerHTML={{__html: comment.author.node.name}}
                />
                <time className="italic">{comment.date}</time>
              </div>
            </header>
            <div dangerouslySetInnerHTML={{__html: comment.content}} />
          </article>
        ))}
      </section>
    </article>
  )
}

Last updated

Was this helpful?