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?