Next.js app目录中如何根据状态值动态设置metadata?
在Next.js 13 App目录中根据状态动态修改页面标题
两种场景的解决方案
场景1:标题依赖服务端数据/路由参数(静态或动态服务端场景)
这种情况可以用generateMetadata函数替代静态metadata对象,它支持异步操作,能获取路由参数、请求信息等,返回动态的metadata:
import type { Metadata, ResolvingMetadata } from 'next'; import { getPostById } from '@/lib/posts'; // 适用于page或layout组件 export async function generateMetadata( { params, searchParams }: { params: { id: string }, searchParams: { [key: string]: string | string[] | undefined } }, parent: ResolvingMetadata ): Promise<Metadata> { // 获取路由参数中的id const postId = params.id; // 异步获取数据 const post = await getPostById(postId); // 可结合父级metadata做扩展修改 const previousImages = (await parent).openGraph?.images || []; return { title: post ? `${post.title} - 我的博客` : '文章不存在', description: post?.excerpt || '未找到文章描述', openGraph: { images: [...previousImages, post?.coverImage], }, }; } export default function PostPage({ params }: { params: { id: string } }) { return <div>文章内容</div>; }
场景2:标题依赖客户端组件内部状态(比如用户交互后的状态)
如果标题需要根据客户端useState、useReducer等状态动态变化,generateMetadata无法访问客户端状态,这时候可以直接在客户端组件中操作document.title,或用useEffect监听状态变化更新标题:
'use client'; // 标记为客户端组件 import { useState, useEffect } from 'react'; export default function CounterPage() { const [count, setCount] = useState(0); // 监听count状态变化,同步更新页面标题 useEffect(() => { document.title = `计数器: ${count}`; }, [count]); return ( <div> <p>当前计数: {count}</p> <button onClick={() => setCount(count + 1)}>增加</button> <button onClick={() => setCount(count - 1)}>减少</button> </div> ); }
注意:客户端修改标题的方式,页面首次渲染时会先显示
generateMetadata或静态metadata设置的标题,之后才会被客户端状态更新的标题替换,属于正常的客户端 hydration 后更新逻辑。
内容的提问来源于stack exchange,提问作者pvp11
相关产品推荐
相关产品推荐

