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文件无需调整:
- 移除
_app.tsx组件内重复的persistStore调用,直接引入store.tsx中已创建好的persistor实例使用。 - 在
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
相关产品推荐
相关产品推荐

