nextjs15 怎么根据接口动态设置metadata?

如题,我看官方示例,这是要请求两次?在page请求一次,然后在generateMetadata又请求一次?

export async function generateMetadata({ params, searchParams }, parent) {
  // ....
  return {
    title: "xxx",
  }
}
 
export default function Page({ params, searchParams }) {
    // 业务请求,请求好接口,再设置Metadata
}

对应文档地址

阅读 1.4k
avatarAI BotBETA
在 Next.js 15 中,`generateMetadata` 函数确实是在服务器端渲染(SSR)阶段之前运行的,这意味着它会在页面组件(如 `Page` 函数组件)的数据请求之前执行。因此,为了避免重复请求数据,你可以采取以下几种策略:

1. **在 `generateMetadata` 中请求数据**:
   如果你希望在设置元数据时就获取数据,可以在 `generateMetadata` 函数中直接发起数据请求。这样,当页面组件渲染时,数据已经准备好,无需再次请求。

export async function generateMetadata({ params, searchParams }, parent) {

 const response = await fetchSomeData(params, searchParams); // 假设这是一个数据请求函数
 return {
   title: response.title,
   // 其他元数据...
 };

}

export default function Page({ data }) {

 // 业务逻辑,data 可以通过 getServerSideProps 或其他方式传递给页面
 return <div>{data.content}</div>;

}

// 注意:在实际应用中,你可能需要通过 getServerSideProps 或 getInitialProps 来获取数据并传递给 Page 组件。
// 这里为了简化示例,没有展示这部分代码。


2. **利用全局状态管理**:
如果数据请求较为复杂或需要在多个页面间共享,可以考虑使用全局状态管理工具(如 Redux、MobX 或 React 的 Context API)来存储和管理数据。这样,你可以在 `generateMetadata` 和页面组件中共享同一份数据,避免重复请求。

3. **客户端渲染时更新元数据**:
如果数据请求不是必须的或可以延迟到客户端渲染时,你也可以选择在页面组件中请求数据,并在数据获取后通过客户端逻辑更新页面的元数据(如标题)。不过,这种方法通常不推荐用于 SEO 重要的元数据,因为搜索引擎爬虫可能无法捕获到动态更新的元数据。

总之,选择哪种方法取决于你的具体需求,如数据的重要性、请求的复杂度以及是否需要优化 SEO 等。在大多数情况下,直接在 `generateMetadata` 中请求数据是一个简单而有效的解决方案。
2 个回答
  1. 是的,两个函数里分别请求。
  2. 不过没关系,next.js 帮你做了缓存。当然你不放心的话也可以自己缓存。总之就是虽然请求两次,但是实际只发生一次。
  3. 我也觉得这么设计不好,现在的异步处理巨麻烦,但是暂时只能这样。

可以使用共享数据的方式

在 generateMetadata 中获取数据,然后将其传递给 Page 组件。这样可以确保只进行一次请求,同时还能在页面渲染之前设置好元数据。
我写了个示例

// 假设你有一个获取数据的函数 fetchData
async function fetchData(params, searchParams) {
  const response = await fetch(`https://api.example.com/data?param=${params}&search=${searchParams}`);
  const data = await response.json();
  return data;
}

export async function generateMetadata({ params, searchParams }) {
  const data = await fetchData(params, searchParams);
  return {
    title: data.title,
  };
}

export default function Page({ params, searchParams }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function loadData() {
      const fetchedData = await fetchData(params, searchParams);
      setData(fetchedData);
    }
    loadData();
  }, [params, searchParams]);

  if (!data) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>{data.title}</h1>
      {/* 其他页面内容 */}
    </div>
  );
}

逻辑如下:

1.generateMetadata 中的 fetchData 函数用于获取数据并生成元数据。
2.Page 组件使用 useEffect 钩子在组件挂载时进行数据请求,并将数据存储在本地状态中。
3.通过条件渲染确保在数据加载完成之前显示加载状态。
这种方法确保了数据请求只发生一次,并且在页面渲染之前生成元数据。

推荐问题
宣传栏