React18报错:无法在状态树中找到router reducer,请求排查
React18项目路由报错排查与解决
问题概述
项目出现报错:Uncaught Could not find router reducer in state tree, it must be mounted under "router",怀疑connected-react-router与history@5.3.0存在兼容性问题,但无法确定根源。通过Redux DevTools发现流程异常,SSO登录相关的Saga中添加console.log无输出,逻辑未执行。
相关代码
Store.js
import { persistStore, persistReducer } from "redux-persist"; import { configureStore } from "@reduxjs/toolkit"; import storageSession from "redux-persist/es/storage/session"; import { routerHistoryMiddleware, sagaMiddleware, } from "./Container/Middleware"; import history from "./Container/History"; import rootReducer from "./Reducer"; const persistedReducer = persistReducer(persistConfig, rootReducer(history)); const store = configureStore({ reducer: persistedReducer, devTools: process.env.NODE_ENV !== "production", middleware: [sagaMiddleware, routerHistoryMiddleware], });
Reducer.js
import { connectRouter } from "connected-react-router"; import { combineReducers } from "redux"; import { Auth } from "../Reducer/Auth"; export default (history) => combineReducers({ router: connectRouter(history), Auth, });
index.js(路由部分)
const persistor = persistStore(store); sagaMiddleware.run(rootSaga); const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <ConnectedRouter history={history}> <App /> </ConnectedRouter> </PersistGate> </Provider> );
Saga.js(SSO登录相关)
export function* locationChangeWatcher() { yield all([takeLatest(LOCATION_CHANGE, locationChangeWorker)]); } function* locationChangeWorker(action) { const state = yield select((state) => state); const prevPathname = state.Context.renderPath; const nextPathname = action.payload.location.pathname; let query = new URLSearchParams(action.payload.location.search); let ticket = query.get("ticket"); if (!ticket && !window.sessionStorage.getItem("st")) { window.location.assign( SSO_URL + "/cas/login?service=" + encodeURIComponent(window.location.href.replace("#", "")) ); } if (window.location.pathname.split("/")[1] != "") { yield put(getAccess.request()); } if (ticket) { window.sessionStorage.setItem("st", ticket); yield put(initAppl.request()); query.delete("ticket"); history.push(window.location.pathname + "?" + query.toString()); } else { if (prevPathname != nextPathname) { yield put(renderPathChange({ renderPath: nextPathname })); if ( prevPathname != getContextPath() && nextPathname != getContextPath() ) { yield put(reset()); } } } }
问题根源分析
- 版本兼容性冲突:
connected-react-router稳定版(v6.x)仅支持history@4.x,与history@5.x不兼容,会导致router reducer无法正确挂载到Redux state的router节点。 - Redux Persist干扰:persistReducer包装rootReducer后,若未排除router字段,会覆盖或延迟router reducer的初始化,导致ConnectedRouter在初始阶段找不到对应的state节点。
- Saga未触发关联问题:由于router reducer未正常挂载,
LOCATION_CHANGEaction无法正确触发,导致监听该action的Saga逻辑完全不执行。
解决办法
1. 降级history版本
将history版本降级到兼容的4.10.1:
npm install history@4.10.1 --save
2. 调整Redux Persist配置
在persistConfig中添加blacklist: ['router'],排除无需持久化的router状态,避免干扰其初始化:
// Store.js中补充persistConfig定义 const persistConfig = { key: 'root', storage: storageSession, blacklist: ['router'] };
3. 确认router中间件配置正确性
确保routerHistoryMiddleware是通过connected-react-router的routerMiddleware创建的:
// Container/Middleware.js import { routerMiddleware } from 'connected-react-router'; import history from './History'; export const routerHistoryMiddleware = routerMiddleware(history);
4. 调整组件渲染顺序(可选)
若PersistGate的加载延迟导致初始阶段router状态不可用,可将ConnectedRouter移到PersistGate外部(仅当路由逻辑不依赖持久化数据时适用):
// index.js root.render( <Provider store={store}> <ConnectedRouter history={history}> <PersistGate loading={null} persistor={persistor}> <App /> </PersistGate> </ConnectedRouter> </Provider> );
内容的提问来源于stack exchange,提问作者user1190842
相关产品推荐
相关产品推荐

