Next.js 13配置Redux Toolkit持久化遇存储创建失败求助
Next.js 13 实现 Redux Toolkit 持久化的正确方案
问题原因
你遇到的redux-persist failed to create sync storage. falling back to noop storage错误,核心原因是Next.js 服务端渲染(SSR)环境中不存在浏览器的localStorage,而redux-persist默认依赖localStorage作为存储介质,服务端初始化时无法访问该对象,因此触发警告并回退到空操作存储。
解决方案
1. 修改 store.js:适配服务端/客户端存储
替换默认的storage导入,添加服务端 fallback 的空存储实现,确保在服务端不会报错:
import { configureStore } from "@reduxjs/toolkit"; import authenticateSlice from "./slices/authenticateSlice"; import { persistReducer } from "redux-persist"; import createWebStorage from "redux-persist/lib/storage/createWebStorage"; import { encryptTransform } from "redux-persist-transform-encrypt"; import { combineReducers } from "redux"; // 创建服务端用的空存储,避免SSR报错 const createNoopStorage = () => { return { getItem() { return Promise.resolve(null); }, setItem(_key, value) { return Promise.resolve(value); }, removeItem() { return Promise.resolve(); }, }; }; // 客户端用localStorage,服务端用空存储 const storage = typeof window !== "undefined" ? createWebStorage("local") : createNoopStorage(); const reducers = combineReducers({ auth: authenticateSlice.reducer, }); let transforms = null; if (process.env.NODE_ENV === "production") { const encrypt = encryptTransform({ secretKey: process.env.NEXT_PUBLIC_REDUX_SECRET, onError: (error) => { // 可在这里添加错误处理逻辑 }, }); transforms = [encrypt]; } const persistConfig = { key: "root", storage, transforms, }; const persistedReducer = persistReducer(persistConfig, reducers); const store = configureStore({ reducer: persistedReducer, // Redux Toolkit 默认已包含thunk,无需手动添加 // middleware: (getDefaultMiddleware) => getDefaultMiddleware(), }); export default store;
2. 修改 _app.js:确保persistStore仅在客户端初始化
persistStore依赖浏览器环境,需避免在服务端执行,可通过useEffect延迟初始化:
import "@/styles/globals.css"; import Head from "next/head"; import Template from "template/index"; import React, { useEffect, useState } from "react"; import store from "next-redux/store"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; import LinearProgress from "@mui/material/LinearProgress"; const App = ({ Component, pageProps }) => { const [persistor, setPersistor] = useState(null); useEffect(() => { // 仅在客户端初始化persistStore import("redux-persist").then(({ persistStore }) => { setPersistor(persistStore(store)); }); }, []); // 等待persistor初始化完成再渲染 if (!persistor) { return <LinearProgress />; } return ( <> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> </Head> <Provider store={store}> <PersistGate persistor={persistor} loading={<LinearProgress />}> <Template> <Component {...pageProps} /> </Template> </PersistGate> </Provider> </> ); }; export default React.memo(App);
关键注意点
- 环境区分:始终确保浏览器专属API(如
localStorage、persistStore)仅在客户端执行 - Redux Toolkit 内置中间件:无需手动添加
thunk,configureStore默认已包含 - 加密逻辑:生产环境的加密转换保持不变,仅在客户端生效
内容的提问来源于stack exchange,提问作者Jc John
相关产品推荐
相关产品推荐

