目前我正在开发 NextJs 14 并使用 App Router。我有一个服务器组件
app/blogs/[slug]/page.tsx
,其中包含如下代码:
import { Metadata } from "next";
type GenerateMetadataProps = {
params: { slug: string };
};
export async function generateMetadata({ params }: GenerateMetadataProps): Promise<Metadata> {
// First call to DB
const blog = await prisma.blog.findFirst({
where: { slug: params.slug },
});
return {
title: `${blog?.title} | Blog - MyWebsite`,
description: blog?.subtitle,
}
}
type BlogDetailPageProps = {
params: { slug: string };
searchParams?: { [key: string]: string | string[] | undefined };
}
const BlogDetailPage = async ({ params, searchParams }: BlogDetailPageProps) => {
const { slug } = params;
// Second call to DB. Kinda working twice for a thing 😥
const blog = await prisma.blog.findFirst({
where: { slug },
});
...
return (
<>
...
</>
);
};
export default BlogDetailPage;
问题是我必须向数据库查询两次才能实现动态元数据(
generateMetadata
)和动态组件(BlogDetailPage
)。调用同一件事两次有点低效。
NextJs 是否可以仅从数据库查询博客一次,但同时利用
generateMetadata
函数和 BlogDetailPage
组件中的数据?
可能的解决方案:
将数据库调用函数包装在 React Cache 中
cache
import { cache } from 'react';
const GetBlogByID = cache(async () => {
// YOUR DB CALL
const blog = await prisma.blog.findFirst({
where: { slug: params.slug },
});
return {
title: `${blog?.title} | Blog - MyWebsite`,
description: blog?.subtitle,
}
})
更换:
const blog =等待 prisma.blog.findFirst({ 其中:{ slug }, });
到
const blog = 等待 GetBlogByID()
您的代码如下:
import { cache } from 'react';
const GetBlogByID = cache(async () => {
// YOUR DB CALL
const blog = await prisma.blog.findFirst({
where: { slug: params.slug },
});
return {
title: `${blog?.title} | Blog - MyWebsite`,
description: blog?.subtitle,
}
})
export async function generateMetadata({ params }: GenerateMetadataProps): Promise<Metadata> {
// First call to DB
const blog = await GetBlogByID()
return {
title: `${blog?.title} | Blog - MyWebsite`,
description: blog?.subtitle,
}
}
type BlogDetailPageProps = {
params: { slug: string };
searchParams?: { [key: string]: string | string[] | undefined };
}
const BlogDetailPage = async ({ params, searchParams }: BlogDetailPageProps) => {
const blog = await GetBlogByID()
...
return (
<>
...
</>
);
};
export default BlogDetailPage;
请阅读:
如果您有任何疑问,请发表评论(如果有必要我会更新答案)