You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Next.js的generateMetadata中正确使用RTK Query查询的问题

问题描述

在Next.js项目中使用RTK Query,需要在generateMetadata中实现数据查询功能。不想额外引入Axios,希望复用RTK Query的请求逻辑,将数据存入store后取用,但当前写法存在问题,需要排查错误原因。

我的RTK API代码:

export const pastEventsApi = rtkQueryApi.injectEndpoints({
  endpoints: (builder) => ({
    getVideo: builder.query<Filters, string>({
      query: (id) => ({
        url: `/pro/ru/block/get_selected_video?uid=${id}`,
      }),
    }),
  }),
});

尝试的generateMetadata代码:

export const generateMetadata = async ({ params }: Params) => {
  const { id } = params;
  const res = await pastEventsApi.endpoints.getVideo.initiate(id);
  return {
    title: res?.data?.title,
  };
};
错误原因与解决方法

核心错误

pastEventsApi.endpoints.getVideo.initiate(id)返回的是RxJS Observable对象,而非标准Promise。直接用await无法获取到请求响应数据,这是代码失效的根本原因。此外,generateMetadata运行在Next.js的服务端(静态生成/SSR阶段),RTK Query的hook无法在此环境运行,需要用服务端兼容的请求方式。

解决方法

方法一:复用RTK Query的fetchBaseQuery(推荐)

如果你的rtkQueryApi是基于fetchBaseQuery创建的,可以直接调用底层的fetchBaseQuery发起请求,复用已配置的API域名、拦截器等逻辑:

export const generateMetadata = async ({ params }: Params) => {
  const { id } = params;
  // 调用RTK的baseQuery发起请求
  const response = await rtkQueryApi.util.fetchBaseQuery({
    url: `/pro/ru/block/get_selected_video?uid=${id}`,
  })();

  // 处理错误情况
  if ('error' in response) {
    return { title: '默认标题' };
  }

  const data = response.data as Filters;
  return {
    title: data.title,
  };
};

方法二:将Observable转换为Promise

若要坚持使用initiate,可以借助RxJS的firstValueFrom将Observable转换为Promise,同时记得清理订阅避免内存泄漏:

import { firstValueFrom } from 'rxjs';

export const generateMetadata = async ({ params }: Params) => {
  const { id } = params;
  const queryObservable = pastEventsApi.endpoints.getVideo.initiate(id);

  try {
    const queryResult = await firstValueFrom(queryObservable);
    return {
      title: queryResult.data?.title,
    };
  } catch (err) {
    return { title: '默认标题' };
  } finally {
    // 取消订阅,避免服务端内存泄漏
    queryObservable.unsubscribe();
  }
};

额外说明

  • 服务端环境下,直接用initiate无法保证数据被正确存入RTK store,若页面组件后续需要复用该数据,建议在组件中使用useQuery,RTK Query会自动识别缓存并复用,无需重复请求。

内容的提问来源于stack exchange,提问作者Глеб Кодрик

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:45:00