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

使用Next.js+Immutable.js+Redux Saga时getServerSideProps序列化initialState.ui失败及服务器端无法dispatch动作问题

解决Next.js + Immutable.js + Redux Saga的两个核心问题

我来帮你拆解并解决这两个困扰你的技术问题,它们都是Immutable.js与Next.js SSR结合时的常见坑:

问题1:/me/profile-setting页面getServerSideProps的JSON序列化错误

问题根源

错误提示里说.initialState.ui无法被JSON序列化,这是因为你的uiReducer和meReducer都用fromJS()把初始状态转换成了Immutable.js的Map对象。而Next.js在SSR过程中,需要把Redux store的状态序列化成JSON传递给客户端,但Immutable的特殊对象结构并不属于原生JSON支持的数据类型,所以直接序列化会失败。

修复方案

最优雅的方式是在next-redux-wrapper的配置中全局处理Immutable状态的序列化/反序列化,这样所有页面的SSR都会自动适配:

修改你的modules/store.js(store的创建文件),在createWrapper时添加序列化逻辑:

import { createWrapper } from 'next-redux-wrapper';
import { fromJS, toJS } from 'immutable';
// ... 其他store相关导入和创建逻辑

const wrapper = createWrapper(makeStore, {
  // 把Immutable状态转成普通JS对象用于序列化
  serializeState: (state) => state.toJS(),
  // 把客户端接收到的JS对象转回Immutable状态
  deserializeState: (state) => fromJS(state),
});

export { wrapper };

另外,还要修正reducer中的HYDRATE处理,确保服务器端的状态能正确合并到客户端:

  • 对于uiReducer:
case HYDRATE:
  // 用merge合并服务器端传来的ui状态,而不是直接返回原state
  return state.merge(fromJS(payload.ui));

问题2:引入Immutable.js后服务器端无法dispatch动作

问题根源

在未使用Immutable前,Redux状态是普通JS对象,next-redux-wrapper的HYDRATE逻辑可以直接合并状态,但换成Immutable后,你的reducer对HYDRATE的处理没有正确适配Immutable的结构,导致服务器端dispatch的动作状态无法传递到客户端;另外,也可能是状态更新时没有用Immutable的API导致状态没变化。

修复方案

  1. 修正reducer中的HYDRATE和状态更新逻辑:

    • meReducer的HYDRATE处理:如果服务器端传来的payload.me是普通JS对象(因为序列化转成了JS),要先转成Immutable:
    case HYDRATE:
      console.log({ payload });
      return state.set("currentPage", fromJS(payload.me.currentPage));
    
    • 确保所有状态更新都用Immutable的API(比如set、merge),不要直接修改状态对象。
  2. 验证服务器端dispatch的动作是否生效:
    在meReducer的SWITCH_ME_PAGE case中加个日志,确认服务器端dispatch时是否触发了状态更新:

    case Actions.SWITCH_ME_PAGE:
      console.log('服务器端触发页面切换:', payload);
      return state.set("currentPage", payload);
    
  3. 组件中获取状态时用Immutable的get方法:
    比如在组件中获取currentPage时,要这样写:

    const currentPage = useSelector(state => state.me.get('currentPage'));
    

    不要直接用state.me.currentPage,因为me是Immutable对象,不是普通JS对象。

额外小提示

  • 所有reducer的初始状态都要用fromJS()包裹,保持状态结构统一;
  • 如果你在组件中需要把Immutable对象转成普通JS对象使用,可以用toJS()方法,比如state.ui.toJS(),但注意不要频繁调用,避免性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:12:28