Reputation: 21
I have problem configuring connect-react-router. I keep getting Error: Could not find router reducer in state tree, it must be mounted under "router"
.
I'm using react, redux-toolkit, typescript and using this react template as base. I have seen all the questions and answers related to this error and tried, but nothing worked. I'm using history
with version 4.10.1
Here is my code, can someone help me to point out where is the issue?
reducers.ts
/**
* Combine all reducers in this file and export the combined reducers.
*/
import { combineReducers } from '@reduxjs/toolkit';
import { connectRouter } from 'connected-react-router';
import { InjectedReducersType } from 'utils/types/injector-typings';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
/**
* Merges the main reducer with the router state and dynamically injected reducers
*/
export function createReducer(injectedReducers: InjectedReducersType = {}) {
// Initially we don't have any injectedReducers, so returning identity function to avoid the error
if (Object.keys(injectedReducers).length === 0) {
return state => state;
} else {
return combineReducers({
router: connectRouter(history),
...injectedReducers,
});
}
}
export { history };
configureStore.ts
/**
* Create the store with dynamic reducers
*/
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { createInjectorsEnhancer } from 'redux-injectors';
import createSagaMiddleware from 'redux-saga';
import { routerMiddleware } from 'connected-react-router';
import { createReducer, history } from './reducers';
export function configureAppStore() {
const reduxSagaMonitorOptions = {};
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
const connectedRouterMiddleware = routerMiddleware(history);
const { run: runSaga } = sagaMiddleware;
// Create the store with saga, router middleware
const middlewares = [sagaMiddleware, connectedRouterMiddleware];
const enhancers = [
createInjectorsEnhancer({
createReducer,
runSaga,
}),
];
const customizedDefaultMiddleware = getDefaultMiddleware({
serializableCheck: false,
});
return configureStore({
reducer: createReducer(),
middleware: [...customizedDefaultMiddleware, ...middlewares],
devTools: process.env.NODE_ENV !== 'production',
enhancers,
});
}
And in my App file, I'm using it via Provider like this:
/**
*
* App
*
* This component is the skeleton around the actual pages, and should only
* contain code that should be seen on all pages. (e.g. navigation bar)
*/
import * as React from 'react';
import {
AppLayout,
AppStyleProvider,
AppThemeProvider,
ContextProvider,
} from './@app';
import { ConnectedRouter } from 'connected-react-router';
import AuthRoutes from './@app/utility/AuthRoutes';
import { CssBaseline } from '@material-ui/core';
import { history } from '../store/reducers';
import { HelmetProvider } from 'react-helmet-async';
import { Provider } from 'react-redux';
import { configureAppStore } from '../store/configureStore';
const store = configureAppStore();
export function App() {
return (
<ContextProvider>
<Provider store={store}>
<AppThemeProvider>
<AppStyleProvider>
<ConnectedRouter history={history}>
<AuthRoutes>
<CssBaseline />
<HelmetProvider>
<AppLayout />
</HelmetProvider>
</AuthRoutes>
</ConnectedRouter>
</AppStyleProvider>
</AppThemeProvider>
</Provider>
</ContextProvider>
);
}
I didn't get any compilation errors, but when I run the app I get Error: Could not find router reducer in state tree, it must be mounted under "router"
Upvotes: 0
Views: 1089
Reputation: 42160
This is honestly a very strange setup that you have here. You initially create the store with no reducers and inject them all after the fact.
Your createReducer()
function is called by configureAppStore()
without any arguments. When this happens, you are returning a reducer which does not have the required router
property. Why? Your app will always get initialized without a router
reducer.
export function createReducer(injectedReducers: InjectedReducersType = {}) {
// Initially we don't have any injectedReducers, so returning identity function to avoid the error
if (Object.keys(injectedReducers).length === 0) {
return (state) => state;
} else {
return combineReducers({
router: connectRouter(history),
...injectedReducers
});
}
}
I fixed the error by removing this condition.
export function createReducer(injectedReducers: InjectedReducersType = {}) {
return combineReducers({
router: connectRouter(history),
...injectedReducers
});
}
Upvotes: 2