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

Next.js集成redux-persist初始加载3-5秒白屏及非序列化报错问题

问题现象

未集成redux-persist时项目运行完全正常,引入该依赖后,每次刷新页面都会出现3-5秒的空白白屏,浏览器控制台抛出两类错误:

A non-serializable value was detected in an action, in the path: err. Value: Error: redux-persist: persist timed out for persist key "root"
at eval (persistReducer.js?6c08:67:1)

next-dev.js?3515:25 A non-serializable value was detected in an action, in the path: register. Value: ƒ register(key) {


原问题附实现代码

store.tsx

// store.tsx 
import { combineReducers, configureStore } from '@reduxjs/toolkit'
import { persistReducer,persistStore } from 'redux-persist'
import storage from 'redux-persist/lib/storage';

import asideRightReducer from './asideRightSlice'

const persistConfig = {
  key: 'root',
  storage,
  
};

const reducers = combineReducers({ asideRight: asideRightReducer });
const persistedReducer = persistReducer(persistConfig, reducers);

export const store = configureStore({
  reducer: persistedReducer,
});

export const persistor = persistStore(store)

export type RootState = ReturnType<typeof store.getState>

export type AppDispatch = typeof store.dispatch

_app.tsx

// _app.tsx
* imports */

type AppPropsGetInitialProps = AppProps & {
  initialAsideLeftHandler: string;
} & {
  initialAsideRightHandler: string;
} & {
  initialIsAsideRightOpen: string;
};

function MyApp({
  Component,
  pageProps,
  initialAsideLeftHandler,
  initialAsideRightHandler,
  initialIsAsideRightOpen,
}: AppPropsGetInitialProps) {

  const persistor = persistStore(store);
  
  return (
    <Provider store={store}>
       <PersistGate loading={null} persistor={persistor}>
        <Layout
          initialAsideLeftHandler={initialAsideLeftHandler}
          initialAsideRightHandler={initialAsideRightHandler}
          initialIsAsideRightOpen={initialIsAsideRightOpen}
        >
          <Component {...pageProps} />
        </Layout>
      </PersistGate>
    </Provider>
  );
}

MyApp.getInitialProps = async (appContext: AppContext) => {
  /* getInitialProps */
  };
};

export default MyApp;

asideRightSlice.tsx

// asideRightSlice.tsx
import { createSlice, PayloadAction } from '@reduxjs/toolkit'

import type { RootState } from '../store/store'

interface isAsideRightType {
    isAsideRightOpen: boolean
}

const initialState: isAsideRightType = {
    isAsideRightOpen: true 
}

export const asideRightSlice = createSlice({
    name: "isAsideRightOpen",
    initialState,
    reducers: {
        setIsAsideRightOpen: (state, action: PayloadAction<boolean>) => {
            state.isAsideRightOpen = action.payload
        }
    }
})

export const { setIsAsideRightOpen } = asideRightSlice.actions

export const selectIsAsideRightOpen = (state: RootState) => state.asideRight.isAsideRightOpen

export default asideRightSlice.reducer

问题根因
  • 重复初始化persistor实例:store.tsx中已经创建并导出了persistor,但_app.tsx组件渲染函数内又重复执行persistStore(store),每次组件重渲染都会生成新实例,打断上一轮持久化流程,最终触发persist超时错误,PersistGate一直停留在加载状态(配置的loading为null,所以显示白屏)。
  • Redux Toolkit默认开启序列化检查,redux-persist内部派发的action会携带非序列化值(函数、Error实例),直接被检查逻辑拦截报错,阻塞状态初始化流程。

修复方案

共两处修改,slice文件无需调整:

  1. 移除_app.tsx组件内重复的persistStore调用,直接引入store.tsx中已创建好的persistor实例使用。
  2. 在configureStore配置中,添加对redux-persist内部action类型的序列化检查忽略规则,避免误拦截。

修复后store.tsx

// store.tsx 
import { combineReducers, configureStore } from '@reduxjs/toolkit'
// 引入redux-persist内置的action类型常量
import { persistReducer,persistStore, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist'
import storage from 'redux-persist/lib/storage';

import asideRightReducer from './asideRightSlice'

const persistConfig = {
  key: 'root',
  storage,
};

const reducers = combineReducers({ asideRight: asideRightReducer });
const persistedReducer = persistReducer(persistConfig, reducers);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        // 忽略redux-persist内部action,跳过序列化检查
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }),
});

export const persistor = persistStore(store)

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

修复后_app.tsx核心调整

// _app.tsx
// 直接从store文件引入已创建的实例,删除组件内重复创建persistor的逻辑
import { store, persistor } from './store/store'

// 其余导入、类型定义保持不变

function MyApp({
  Component,
  pageProps,
  initialAsideLeftHandler,
  initialAsideRightHandler,
  initialIsAsideRightOpen,
}: AppPropsGetInitialProps) {
  // 删除 const persistor = persistStore(store); 这行重复代码
  
  return (
    <Provider store={store}>
       <PersistGate loading={null} persistor={persistor}>
        <Layout
          initialAsideLeftHandler={initialAsideLeftHandler}
          initialAsideRightHandler={initialAsideRightHandler}
          initialIsAsideRightOpen={initialIsAsideRightOpen}
        >
          <Component {...pageProps} />
        </Layout>
      </PersistGate>
    </Provider>
  );
}

// 其余getInitialProps、导出逻辑保持不变

修改完成后重启开发服务,白屏和控制台报错问题即可解决。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:18:28