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

如何在Next.js App Router中结合Redux-Persist持久化数据

在Next.js App Router中结合Redux官方makeStore方案实现redux-persist持久化

问题根源

你遇到的类型错误是因为persistStore要求传入已初始化的Redux Store实例,但你直接传了makeStore这个创建Store的函数,导致类型不兼容。同时由于Next.js App Router的服务端渲染特性,redux-persist依赖的localStorage只能在客户端环境运行,必须调整代码结构适配。

适配方案

以下是针对现有代码的修改步骤:

1. 调整store.js:移除全局persistor,导出必要工具

import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { configureStore, combineReducers } from '@reduxjs/toolkit'
import {userReducer} from "./user/userSlice"

const combinedReducers = combineReducers({
  user: userReducer,
})

const persistedReducer = persistReducer(
  {
      key: 'root',
      storage,
      whitelist: ['user'],
  },
  combinedReducers
)

export const makeStore = () => {
  return configureStore({
    reducer: persistedReducer,
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware({
            serializableCheck: {
                ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
            },
        }),
  })
}

// 移除全局persistor,改为在客户端创建
export type AppStore = ReturnType<typeof makeStore>
export type RootState = ReturnType<AppStore['getState']>
export type AppDispatch = AppStore['dispatch']
// 导出persistStore供客户端使用
export { persistStore }

2. 修改StoreProvider:在客户端创建persistor并使用PersistGate

"use client";

import { useRef } from "react";
import { Provider } from "react-redux";
import { PersistGate } from 'redux-persist/integration/react'
import { makeStore, AppStore, persistStore } from "../redux/store";

export default function StoreProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const storeRef = useRef<AppStore>();
  const persistorRef = useRef<ReturnType<typeof persistStore>>();

  if (!storeRef.current) {
    // 首次渲染创建Store实例
    storeRef.current = makeStore();
    // 基于已创建的Store生成persistor
    persistorRef.current = persistStore(storeRef.current);
  }

  return (
    <Provider store={storeRef.current}>
      {/* 等待持久化数据恢复后再渲染子组件 */}
      <PersistGate loading={null} persistor={persistorRef.current!}>
        {children}
      </PersistGate>
    </Provider>
  );
}

3. layout.js保持不变

你的RootLayout已经正确用StoreProvider包裹了子组件,无需修改。

核心要点说明

  • 实例化时机:Store和persistor都只在客户端组件首次渲染时创建一次,避免服务端运行时访问localStorage的错误。
  • 类型匹配:现在persistStore接收的是makeStore()返回的Store实例,完全符合类型要求。
  • PersistGate作用:确保应用在持久化数据加载完成后再渲染,避免初始状态为空导致的UI异常。

内容的提问来源于stack exchange,提问作者Kos-Mos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:20:20