如何使用 Next.js 中带有应用路由器的客户端组件更改页面标题?
我正在使用 Next.js 构建博客,并使用新的应用路由器进行导航。但是,我遇到了一个问题,即每个博客页面都显示相同的标题和说明。 在调查代码后,我发现标题和说明是从 layout.js 文件中导出为 Metadata() 的,这似乎是问题的主要原因。当我尝试在单个博客页面中使用 Metadata() 时,它没有按预期工作。
有没有办法解决这个问题,并为每个博客页面设置不同的标题和说明, 即使在使用应用路由器并包含非 SSR 页面(如客户端)时也是如此? 我将不胜感激有关如何解决此问题的任何指导或建议。
如果您的页面标题是静态的,那么您可以创建一个新的
layout.js
文件来导出带有新标题的元数据。
.
├── app/
│ ├── client/
│ │ ├── layout.js // Create new title here
│ │ └── page.js // 'use client'
│ ├── layout.js
│ └── page.js
├── package.json
└── next.config.js
因此在上面的例子中,如果
client/page.js
有一个
'use client'
指令,那么您可以通过创建一个兄弟
layout.js
文件来更改页面标题,该文件只是呈现子项并更新标题:
client/layout.js
export const metadata = {
title: 'New Title'
}
export default function ClientLayout({ children }) {
return children
}
如果页面标题基于来自 API 的动态内容,那么您可以将上述方法用于默认的服务器端实现,然后在呈现
client/page.js
时更新
useEffect
内的
document.title
。
在 Next.js 13 中,您可以通过从任何 layout.js 或 page.js 文件 导出 Metadata 对象 来定义静态元数据,但您可能希望为每个页面生成动态元数据(取决于该页面所获取内容的元数据)。 要执行动态元数据,您需要 导出 generateMetadata 函数
您还可能会发现使用像 next-seo 这样的包更容易,尽管我从 Next.js 12 开始就没有使用过它,也不知道它是否适用于新的应用程序目录。
我的方式: AppPage.tsx
'use client'
const AppPage = ({ title, children, className, ...rest }) => {
useEffect(() => {
if (title) document.title = title
}, [title])
return <div className={className}>{children}</div>
}