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

NextJS中getServerSideProps无法初始化客户端状态(next-redux-wrapper等)

问题解决:Next.js + Redux-Saga 刷新页面后Redux状态丢失

问题原因

  • 仅在首页的getServerSideProps中触发了数据获取逻辑,/enquiries页面刷新时,服务端未执行数据请求,导致服务端生成的Redux状态为空,客户端hydration后状态也为空。
  • store/index.js中未正确导出wrapper实例,导致_app.ts中的hydration逻辑无法正常工作。
  • Redux Slice中的HYDRATE处理可优化,避免潜在状态合并问题。

具体修复步骤

1. 修复Store配置,导出wrapper实例

修改store/index.js,添加createWrapper调用并导出实例:

import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import createSagaMiddleware from "redux-saga";
import enquiryReducer from '../store/enquiry/slice';
import { createWrapper } from 'next-redux-wrapper';
import rootSaga from '../sagas/index'; 

const makeStore = () => {
  const sagaMiddleware = createSagaMiddleware();
  const store = configureStore({
    reducer: {
      enquiry: enquiryReducer,
    },
    middleware: [...getDefaultMiddleware({ thunk: false }), sagaMiddleware],
    devTools: true
  })
  //@ts-ignore
  store.sagaTask = sagaMiddleware.run(rootSaga);
  return store;
}

// 创建并导出wrapper实例
export const wrapper = createWrapper<AppStore>(makeStore);

const store = makeStore();
export type AppStore = ReturnType<typeof makeStore>;
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch

2. 为/enquiries页面添加服务端数据获取逻辑

在pages/enquiries.js中添加getServerSideProps,触发数据请求并等待Saga完成:

import { wrapper } from '../store';
import { END } from 'redux-saga';
import { startedLoadingEnquiries } from '../store/enquiry/slice';
// 其他组件导入...

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async () => {
    await store.dispatch(startedLoadingEnquiries());
    store.dispatch(END);
    await (store as any).sagaTask.toPromise();
    return { props: {} };
  }
);

// 页面组件代码...

3. 优化Slice中的HYDRATE处理(可选但推荐)

将Slice的extraReducers改为RTK推荐的builder模式,确保状态合并正确:

import { PayloadAction, createSlice } from '@reduxjs/toolkit'
import { HYDRATE } from 'next-redux-wrapper';
import { RootState } from '../index';

export enum LoadingTracker {
  NotStarted,
  Loading,
  Success,
  Failed
}

// 补充Enquiry类型定义
type Enquiry = {
  id: string;
  // 其他字段...
};

type EnquiryState = {
  enquiries: Enquiry[],
  loadingTracker: LoadingTracker
}

const initialState: EnquiryState = {
  enquiries: [],
  loadingTracker: LoadingTracker.NotStarted
}

export const enquirySlice = createSlice({
  name: 'enquiries',
  initialState,
  reducers: {
    loadEnquiries: (state, action: PayloadAction<Enquiry[]>) => {
      state.enquiries = action.payload;
      state.loadingTracker = LoadingTracker.Success
    },
    failedLoadEnquiries: (state) => {
      state.loadingTracker = LoadingTracker.Failed;
    },
    startedLoadingEnquiries: (state) => {
      state.loadingTracker = LoadingTracker.Loading;
    }
  },
  extraReducers: (builder) => {
    builder.addCase(HYDRATE, (state, action) => {
      return {
        ...state,
        ...action.payload.enquiry
      };
    });
  },
});

export const { loadEnquiries, failedLoadEnquiries, startedLoadingEnquiries } = enquirySlice.actions;
export default enquirySlice.reducer;

完成以上修改后,刷新/enquiries页面时,服务端会触发数据请求并将填充好的状态传递给客户端,hydration后Redux状态将保持正确,页面可正常展示列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:36:31