DEV Community

Haruka Kato
Haruka Kato

Posted on • Updated on

Error: Could not find router reducer in state tree, it must be mounted under "router" 

https://gyazo.com/64dd39bc0d236709ea16112c2775b51d

Hello there! I was trying to introduce google auth to my react-redux app for over a week and I was finally able to solve the problem.
First, I encountered this problem and I read almost all the solutions online but it did not help at all!

If you look at those solutions, most of them "decrease the version of history", but if it did not work, maybe you wanna take a look at my article!

I followed this tutorial https://github.com/GoZaddy/react-redux-firebase-article/blob/master/src to introduce Google Auth to my application. And its index.js is as follows.

index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import { createStore, compose } from "redux";
import { Provider } from "react-redux";
import { ReactReduxFirebaseProvider } from "react-redux-firebase";
import { createFirestoreInstance } from "redux-firestore";
import { rootReducer } from "./ducks/reducers";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import * as serviceWorker from "./serviceWorker";

const firebaseConfig = {
  apiKey: "AIzaSyBJTFQkg95Aj-s_NsA77mco8ZVG2siLv4U",
  authDomain: "react-redux-firebase-article.firebaseapp.com",
  databaseURL: "https://react-redux-firebase-article.firebaseio.com",
  projectId: "react-redux-firebase-article",
  storageBucket: "react-redux-firebase-article.appspot.com",
  messagingSenderId: "781345165856",
  appId: "1:781345165856:web:45fd42a60e5bb365172245",
  measurementId: "G-XFR3YXLCGW",
};

const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true,
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

const initialState = {};
const store = createStore(rootReducer, initialState);

const rrfProps = {
  firebase,
  config: rrfConfig,
  dispatch: store.dispatch,
  createFirestoreInstance,
};
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <ReactReduxFirebaseProvider {...rrfProps}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </ReactReduxFirebaseProvider>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
Enter fullscreen mode Exit fullscreen mode

I tried every solution online about this error so I thought

Error: Could not find router reducer in state tree, it must be mounted under "router" 
Enter fullscreen mode Exit fullscreen mode

I thought this error was occurring because of my Ducks pattern. So I tried to convert this index.js file to Ducks pattern then I was even more stuck and I didn't know what to do.

I spent a lot of time looking for how I can convert this Google Auth index.js file to Ducks pattern but I found zero articles. I followed some articles that explain how to convert from Re-ducks pattern to Ducks pattern and I followed but I started to get different errors continuously.

So I hired a tutor and asked a question and I was finally able to solve this problem.

Here is the important point. If you follow Ducks pattern, you don't wanna convert Google Auth index.js file to Ducks pattern because it makes things very complicated.

If you find this error while you are working on react-redux-firebase

Error: Could not find router reducer in state tree, it must be mounted under "router" 

you should look at this official document.
https://www.npmjs.com/package/connected-react-router

For me, my problem was I did not have

 <Provider store={store}>
Enter fullscreen mode Exit fullscreen mode

in my App.js file.

Here is my App.js file.

import React, { Suspense } from 'react';
import { BrowserRouter as Router,Switch, Route} from 'react-router-dom';
import Top from './components/Top';
import Contact from './components/Contact';
import SignUp from './components/SignUp';
import SignIn from './components/SignIn';
import SignOut from './components/SignOut';
import { ConnectedRouter } from 'connected-react-router';
import {history} from './configureStore';
import { Provider } from 'react-redux'
import {configureStore} from './configureStore';
const store = configureStore();

const App = () => {


    return (
        <React.Fragment>
            <Provider store={store}>
                <ConnectedRouter history={history}>
                            <Switch>
                                <Route exact path="/" component={Top}/>
                            </Switch>
                            <Switch>
                                <Route exact path="/contact" component={Contact}/>
                            </Switch>
                            <Switch>
                                <Route exact path="/signup" component={SignUp}/>
                            </Switch>
                            <Switch>
                                <Route exact path="/signin" component={SignIn}/>
                            </Switch>
                            <Switch>
                                <Route exact path="/signout" component={SignOut}/>
                            </Switch>
                            <Switch>
                                <Route exact path="/top" component={Top}/>
                            </Switch>
                </ConnectedRouter>
                </Provider>
        </React.Fragment>
    )

}
export default App;

Enter fullscreen mode Exit fullscreen mode

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
import { Provider } from 'react-redux';
import {configureStore} from './configureStore';
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import { useHistory } from "react-router-dom";
import { createFirestoreInstance } from "redux-firestore";
import { BrowserRouter } from "react-router-dom";
import { useDispatch, useSelector } from 'react-redux';
import { ReactReduxFirebaseProvider } from "react-redux-firebase";
import { createStore, compose } from "redux";
import { rootReducer } from "./rootReducer";

  const firebaseConfig = {
    apiKey: "AIzaSyAOSBfTj_VQ4byWAAOWDhAsklmZtk2W_iE",
    authDomain: "stresstackle-599d9.firebaseapp.com",
    projectId: "stresstackle-599d9",
    storageBucket: "stresstackle-599d9.appspot.com",
    messagingSenderId: "930013144401",
    appId: "1:930013144401:web:79b25db79f4118359fdf70",
    measurementId: "G-J26Y6MYWV3"
  };

const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true,
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

const initialState = {};
const store = createStore(rootReducer, initialState);

const rrfProps = {
  firebase,
  config: rrfConfig,
  dispatch: store.dispatch,
  createFirestoreInstance,
};

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <ReactReduxFirebaseProvider {...rrfProps}>

          <App />

      </ReactReduxFirebaseProvider>
    </Provider>
  </React.StrictMode>,
    document.getElementById('root')
    );
Enter fullscreen mode Exit fullscreen mode

/src/configureStore.js

import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import {rootReducer} from './rootReducer';
// import thunk from 'redux-thunk';
// import logger from 'redux-logger';


const createBrowserHistory = require('history').createBrowserHistory;




export const history = createBrowserHistory();
//これをApp.jsに渡した


const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export  function configureStore(preloadedState) {

    const store = createStore(
        rootReducer(history),
        preloadedState,
        composeEnhancers(
            applyMiddleware(
                routerMiddleware( history),
            )
        )
    );

    return store;
};
//↑Redux dev toolsとconnectingしている


Enter fullscreen mode Exit fullscreen mode

/src/rootReducer.js

import {combineReducers} from 'redux';
import { connectRouter } from 'connected-react-router';
import {firebaseReducer} from "react-redux-firebase";
import {firestoreReducer} from "redux-firestore";

export const rootReducer =(history) => combineReducers({

    router: connectRouter(history),
    firebase: firebaseReducer,
    firestore: firestoreReducer,
});

//history:履歴管理に必要なもの
//connected-react-router:reduxとつなげられる
//..>..>..>みたいなアプリ上での遷移に対応できる

// title: Consultation,
// inquiry: Consultation
Enter fullscreen mode Exit fullscreen mode

/src/components/SignIn.js

import React, { useState } from 'react';
import { useFirebaseApp } from 'reactfire';
import 'firebase/auth'
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';
import Header from './BasicComponents/Header';
import Footer from './BasicComponents/Footer';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import { StylesProvider } from "@material-ui/core/styles";
import styled from "styled-components";
import { useFirebase } from "react-redux-firebase";
import { useHistory } from "react-router-dom";
import { useDispatch, useSelector } from 'react-redux';
import { push } from 'connected-react-router'

const useStyles = makeStyles((theme) => ({
    root: {
        flexGrow: 1,
    },
    paper: {
        textAlign: 'center',
        backgroundColor: '#C0C0C0',
        opacity: 0.7,
        borderRadius: 50,
        height: 500,
        paddingTop: 20,
    },
    grid: {
        position: 'block',
        margin: '0 auto',
        marginTop: 50,
        marginBottom: 50,
    },
    input:{
        width: '70%',
        height: 50,
        fontSize: 15,
        padding: '.3em',
        borderRadius: 10,
        border: '1px solid #aaa',
    },
    input1:{
        width: '70%',
        height: 50,
        fontSize: 15,
        padding: '.1em',
        marginRight: 5,
        borderRadius: 10,
        border: '1px solid #aaa',
    },
    p1:{
        textAlign: 'left',
        paddingLeft: 80,
        fontColor: 'black',
    },
    button1:{
        backgroundColor: 'pink',
        color: 'black',
        width: '35%',
        borderRadius:40,
        marginTop: 10,
    },
    button2:{
        backgroundColor: '#9400D3',
        color: 'black',
        width: '35%',
        borderRadius:40,
    },
}));


export default function SignUp() {
    const classes = useStyles();
    const auth = useSelector(state => state.auth); //global stateを呼び出すため,Dev toolをみて決めてる
    const dispatch = useDispatch();
    const firebase = useFirebase();

    const signInWithGoogle = () => {
        firebase
            .login({
                provider: "google",
                type: "popup",
            })
            .then(() => {
                dispatch({ type: "USE_PROFILE" });
                dispatch(push('/top'));
            });
    };


    return (
            <div className={classes.root}>
                <Header/>
                <Grid >
                    <Grid item xs={5} className={classes.grid}>
                        <Paper className={classes.paper}>
                            <form>
                            <h1>Welcome back!</h1>
                              <p>Please sign in below to continue</p>
                                 <p className={classes.p1}>Email address</p>
                                    <input
                                        type="text"
                                        name="Email"
                                        className={classes.input1}
                                    /><br></br>
                                    <p className={classes.p1}>Password</p>
                                    <input
                                        type="password"
                                        name="password"
                                        className={classes.input}
                                    /><br></br>
                                        <Button classes={{root: classes.button1,}} type="submit">
                                            Sign in
                                        </Button>
                                            <p>or</p>
                                        <Button classes={{root: classes.button2,}}
                                                onClick={(event) => {
                                                    event.preventDefault();
                                                    signInWithGoogle();
                                                }} >
                                            Sign in with Gmail
                                        </Button><br></br>
                            <p >Forgot Password?</p>
                            </form>
                        </Paper>
                    </Grid>
                </Grid>
            <Footer/>
        </div>

    );
}
Enter fullscreen mode Exit fullscreen mode

I think this article can be helpful if you are working on react-redux-firebase and find this error because there are not many articles that explain how to solve this error for a react-redux-firebase app.

Error: Could not find router reducer in state tree, it must be mounted under "router" 
Enter fullscreen mode Exit fullscreen mode

Hope this was helpful for you!

Top comments (0)