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
相关产品推荐
相关产品推荐

