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

RTK Query在SSG中提取Rehydration信息失效问题排查

RTK Query SSG 问题排查与疑问解答

问题背景

我按照RTK Query文档的SSR步骤操作:

  • 配置了next-redux-wrapper
  • 在SSG的getStaticProps中发起请求并等待查询完成
  • 添加了extractRehydrationInfo方法并加入日志

运行后终端日志显示所有action.type均不等于HYDRATE,无法合并服务端与客户端的store数据。同时还有疑问:是否需要在SSR/SSG中使用RTK?我希望通过props返回数据实现SSG构建时缓存,比如用RTK Query的数据生成meta描述。


页面SSG代码

export const getStaticProps: GetStaticProps = wrapper.getStaticProps((store) => async (context) => {
  store.dispatch<any>(apiCore.endpoints.getAboutUsInformation.initiate());
  await Promise.all(store.dispatch<any>(apiCore.util.getRunningQueriesThunk()));
  return { props: {}, };
})

API创建代码及日志

export const apiCore = createApi({
  tagTypes: ["events-get", "about-us-get"],
  refetchOnMountOrArgChange: 900,
  extractRehydrationInfo(action, { reducerPath }) {
    console.log("extractRehydrationInfo", action.type, action.type == HYDRATE);
    if (action.type === HYDRATE) {
      return action.payload[reducerPath];
    }
  },
  baseQuery: fetchBaseQuery({ baseUrl: process.env.NEXT_PUBLIC_API_REQUEST }),
  endpoints: (build) => ({
    getAboutUsInformation: build.query<ApiResponseWrapper<Array<AboutUsModel>>, void>({
      providesTags: ["about-us-get"],
      query: () => 'helper/pages',
    }),
  }),
})

Redux Store配置

const entities = combineReducers({
  usersSlice: usersSlice,
  eventsSlice: eventsSlice,
  termConditionSlice: termConditionSlice,
  companiesSlice: companiesSlice,
  aboutUsSlice: aboutUsSlice
})

const ui = combineReducers({
  modals: modalSlice,
  notification: notificationSLice
})

const reducers = combineReducers({
  [apiCore.reducerPath]: apiCore.reducer,
  entities: entities,
  ui: ui,
})

const makeStore = () => configureStore({
  reducer: reducers,
  middleware: getDefaultMiddleware => [
    ...getDefaultMiddleware({ serializableCheck: false }).concat(apiCore.middleware),
  ],
  devTools: process.env.NODE_ENV === 'development',
});

const appStore = makeStore()
setupListeners(appStore.dispatch)

export type AppStore = ReturnType<typeof makeStore>
export type AppState = ReturnType<typeof appStore.getState>
export type AppDispatch = typeof appStore.dispatch
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, AppState, unknown, Action<string>>

export const wrapper = createWrapper<AppStore>(makeStore, { debug: true })
export default appStore

问题排查与解决方案

1. HYDRATE未触发的原因及修复

HYDRATE action是next-redux-wrapper针对**服务端渲染(SSR,即getServerSideProps)**设计的,用于合并服务端与客户端的store状态。而你使用的是getStaticProps(静态站点生成),该逻辑在构建时执行,不会在用户请求阶段触发服务端渲染流程,因此永远不会触发HYDRATE。

SSG场景下RTK Query的正确用法:

  • 在getStaticProps中执行查询并提取结果,直接作为props返回给页面
  • 页面组件通过useQuery的initialData参数复用构建时获取的数据,避免客户端重复请求

修改后的getStaticProps示例:

export const getStaticProps: GetStaticProps = wrapper.getStaticProps((store) => async (context) => {
  // 发起查询并等待请求完成
  const queryPromise = store.dispatch(apiCore.endpoints.getAboutUsInformation.initiate());
  await queryPromise.unwrap();
  
  // 从store中提取查询结果
  const aboutUsQueryResult = apiCore.endpoints.getAboutUsInformation.select()(store.getState());
  
  return { 
    props: { 
      initialAboutUsData: aboutUsQueryResult.data 
    }, 
    revalidate: 900 // 可选:设置增量静态再生的时间间隔
  };
})

页面组件中使用:

export default function AboutUsPage({ initialAboutUsData }) {
  const { data } = useGetAboutUsInformationQuery(undefined, {
    initialData: initialAboutUsData
  });
  
  // 使用data生成meta描述或静态内容
  return <div>{/* 页面内容 */}</div>;
}

2. SSG场景下是否需要使用RTK?

完全可以用,且在复杂场景下有明显优势:

  • 如果你需要构建时缓存+后续请求复用缓存、自动请求去重、标签式缓存失效等特性,RTK Query能帮你简化逻辑
  • 若只是简单的静态数据请求,直接用fetch也能实现,但RTK Query的状态管理能力可以避免重复造轮子

需要注意的是,SSG场景下不需要依赖extractRehydrationInfo,直接通过props传递构建时的数据即可满足需求。

内容的提问来源于stack exchange,提问作者hassan moradnezhad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:17:46