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

如何在无SSR的React Router v7 Framework模式中使用redux-persist与RTK?

React Router v7 Framework模式下redux-persist存储报错解决

问题描述

将React/Vite应用迁移至React Router v7 Framework模式后,执行npm run dev时出现以下错误:

redux-persist failed to create sync storage. falling back to noop storage.
[vite] (ssr) Error when evaluating SSR module virtual:react-router/server-build: storage.getItem is not a function
...
[vite] Internal server error: storage.getItem is not a function

可通过以下步骤复现:

  1. 执行npx create-react-router@latest创建全新应用
  2. 配置react-router.config.ts关闭SSR:
import type { Config } from "@react-router/dev/config";

export default {
  ssr: false,
} satisfies Config;
  1. 创建Redux store及切片:
    ./app/store/store.js
import { configureStore } from "@reduxjs/toolkit";
import storage from "redux-persist/lib/storage";
import { persistReducer, persistStore } from "redux-persist";
import auth from "./authSlice";

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

export const reducer = persistReducer(persistConfig, auth);
export const store = configureStore({ reducer });
export const persistor = persistStore(store);

./app/store/authSlice.js

import { createSlice } from "@reduxjs/toolkit";

export const authSlice = createSlice({
  name: "auth",
  initialState: { token: "" },
  reducers: {
    setToken(state, action) {
      state.token = action.payload;
    },
  },
});

export default authSlice.reducer;
  1. 修改root.tsx添加Redux Provider:
import { Provider } from "react-redux";
import { store } from "./store/store";
import { Outlet } from "react-router";

export default function App() {
  return (
    <Provider store={store}>
      <Outlet />
    </Provider>
  );
}

解决方案

无需替换redux-persist,通过环境兼容的存储引擎配置和客户端延迟初始化即可解决问题:

1. 适配环境的存储引擎配置

修改./app/store/store.js,根据运行环境选择存储引擎:Node环境使用noop存储(不做持久化),浏览器环境使用localStorage:

import { configureStore } from "@reduxjs/toolkit";
import { persistReducer, persistStore } from "redux-persist";
import createNoopStorage from "redux-persist/lib/storage/noop";
import auth from "./authSlice";

// 根据环境动态选择存储引擎
const storage = typeof window !== "undefined" 
  ? require("redux-persist/lib/storage").default 
  : createNoopStorage();

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

export const reducer = persistReducer(persistConfig, auth);
export const store = configureStore({ reducer });

// 仅在客户端初始化persistStore
export let persistor;
if (typeof window !== "undefined") {
  persistor = persistStore(store);
}

2. 客户端延迟初始化PersistGate(若使用)

如果你的应用使用PersistGate,需确保它仅在客户端渲染时加载,修改root.tsx:

import { Provider } from "react-redux";
import { store } from "./store/store";
import { PersistGate } from "redux-persist/integration/react";
import { useEffect, useState } from "react";
import { Outlet } from "react-router";

export default function App() {
  const [clientPersistor, setClientPersistor] = useState(null);

  useEffect(() => {
    // 在客户端环境初始化persistor
    import("./store/store").then((module) => {
      setClientPersistor(module.persistor);
    });
  }, []);

  // 客户端未初始化完成时,直接渲染内容或加载态
  if (!clientPersistor) {
    return <Outlet />;
  }

  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={clientPersistor}>
        <Outlet />
      </PersistGate>
    </Provider>
  );
}

3. 确认SSR配置生效

确保react-router.config.ts中的ssr: false配置正确,避免不必要的SSR预渲染流程:

import type { Config } from "@react-router/dev/config";

export default {
  ssr: false,
} satisfies Config;

原理说明

错误根源是redux-persist在Node环境(SSR评估阶段)尝试访问浏览器专属的localStorage API,而Node环境不存在该接口。即使关闭SSR,React Router Framework模式在启动时仍会执行模块评估,导致store初始化时触发storage访问。通过环境判断切换存储引擎,避免在Node环境调用浏览器API,即可解决该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:53:13