React: Could not find router reducer in state tree, it must be mounted under “router”

Aron Schüler Published


As I was upgrading dependencies for an older project, I ran into the error Could not find router reducer in state tree, it must be mounted under "router" and spent a good amount of time trying to find a solution. Multiple stackoverflow posts were solved by upgrading the history package, but this was not what caused it for me. My project used the connected-react-router package. I migrated this package from major version 4 to major version 6. If you did this as well and now get the following error, I can help you!

Fixing the reducer

As the error suggests, we have a problem with our router reducer. This happens because the redux api changed and it expects a router in your applications call to combineReducers. So, to solve this error, we have to adapt our call to that function. It can be found most-likely in a reducers.js file somewhere in your project.

Importing connectRouter into the reducer.js

First, we have to add the following line to the imports in reducers.js:

// other imports
// [...]
import { connectRouter } from "connected-react-router";

Change reducer signature to accept parameter

Next, we have to modify our root reducers signature. In version 4.x, the reducer took no arguments. In the major versions above, we need the history argument. So change your export from something like export default combineReducers({...}) to:

export default (history) => combineReducers({
  ...
})

Add router argument to combineReducers call

As the combineReducers function of redux expects a router argument, we have to add that named argument to our call and connect to our router there:

export default (history) => combineReducers({
  router: connectRouter(history),
  ...
})

This was the final modification of our reducers.js file. Now, we have to switch to the file that configures and creates our redux store. Most likely, this should be configureStore.js.

Use adapted function in createStore in configureStore.js

Adapt imports

First, we need to change our imports. We don’t want to connect to the router in configureStore.js anymore, as we already do this in our reducer now. So, remove the import of connectRouter:

// Look for something like this line:
// import { connectRouter, routerMiddleware } from 'connected-react-router'
// and change it to
import { routerMiddleware } from "connected-react-router";

Next, we should modify the name under which the default export of reducers.js is imported. I propose some name that uses the imperative, as an indicator what the function does:

// Look for something like this line:
// import rootReducer from './reducers'
// and change it to
import createRootReducer from "./reducers";

Use createRootReducer in createStore redux store creation

As a final step, we have to adapt the way we connect to our router. While it used to be something like connectRouter(history)(rootReducer) we want the createStore function now to be something like:

const store = createStore(
  createRootReducer(history),
  initialState,
  compose(applyMiddleware(routerMiddleware(history))),
);

Done!

Now your application should render again. If it does not, leave your error message in the comments and we’ll figure out a solution together.

If you want to read more tutorials like this, be sure to check out my other JavaScript fixes!


Related Posts

Find posts on similar topics:


Comments