TypeError: Cannot read property 'history' of undefined

20,972

Solution 1

For the / route you should use render like this:

<Route exact path="/" render={() => {
  if (Auth.isUserAuthenticated()) { 
    (<DashboardPage)/>)
  } else {
    (<HomePage/>)
  }
}} />

For your /logout route using <Redirect>

<Route path="/logout" render={() => {
    Auth.deauthenticateUser();
    return <Redirect to={{ pathname: "/login" }} />;
    }}
/>

Solution 2

I post a second solution for the /logout path using withRouter and this.props.history.push('/login').

  1. Point the /logout Route to its own component "Logout"
  2. wrap the Logout component with withRouter method from react-router-dom.

Logout.js

import React, { Component } from "react";
import Auth from "../modules/Auth";
import { withRouter } from "react-router-dom";

class Logout extends Component {
  constructor(props) {
    super(props);
    this.handleLogout = this.handleLogout.bind(this);
  }
  handleLogout() {
    Auth.deauthenticateUser();
    this.props.history.push("/login");
  }
  render() {
    return (
      <div>
        {this.handleLogout()}
      </div>
    );
  }
}
export default withRouter(Logout);
Share:
20,972
Isak La Fleur
Author by

Isak La Fleur

Updated on June 22, 2020

Comments

  • Isak La Fleur
    Isak La Fleur almost 4 years

    I'm trying to redirect the user to the login page when the /logout routes is hit. The auth is working (jwt token is removed, but the app fails to redirect to /login.

    Also If I do to / the app crashes as well.

    On the Login route I uses withRouter from the react-router-dom package wih this I can access the this.props.history.push('/redirect_to_a_new_path'), but when I try to wrap the App component with withRouter method it crashes as well.

    Please help!

    Here is the github repo:

    App.js

    import React, { Component } from "react";
    import {
      BrowserRouter as Router,
      Route,
      Switch,
      withRouter
    } from "react-router-dom";
    import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
    import lightBaseTheme from "material-ui/styles/baseThemes/lightBaseTheme";
    import getMuiTheme from "material-ui/styles/getMuiTheme";
    import injectTapEventPlugin from "react-tap-event-plugin";
    
    // Components
    import Navbar from "./components/Navbar";
    import HomePage from "./components/HomePage";
    import SpotMap from "./components/SpotMap";
    import SignUpPage from "./components/containers/SignUpPage";
    import LoginPage from "./components/containers/LoginPage";
    import DashboardPage from "./components/containers/DashBoardPage";
    import NotFound from "./components/NoteFound";
    import Auth from "./modules/Auth";
    import "./styles/App.css";
    
    injectTapEventPlugin();
    
    const handleLogout = event => {
      Auth.deauthenticateUser();
      this.props.history.push("/login");
    };
    
    const isLoggedIn = event => {
      if (Auth.isUserAuthenticated()) {
        this.props.history.push(DashboardPage);
      } else {
        this.props.history.push(HomePage);
      }
    };
    
    class App extends Component {
      render() {
        return (
          <MuiThemeProvider muiTheme={getMuiTheme(lightBaseTheme)}>
            <Router>
              <div>
                <Navbar />
                <Switch>
                  <Route exact path="/" component={isLoggedIn} />
                  <Route path="/spotmap" component={SpotMap} />
                  <Route path="/dashboard" component={DashboardPage} />
                  <Route path="/signup" component={SignUpPage} />
                  <Route path="/login" component={LoginPage} />
                  <Route path="/logout" component={handleLogout} />
                  <Route component={NotFound} />
                </Switch>
              </div>
            </Router>
          </MuiThemeProvider>
        );
      }
    }
    
    export default App;
    

    This is written in React Router v3 and this is what I need to convert to React Router V4. The routes that does not work for me are the "/" and "logout" routes.

    import Base from './components/Base.jsx';
    import HomePage from './components/HomePage.jsx';
    import DashboardPage from './containers/DashboardPage.jsx';
    import LoginPage from './containers/LoginPage.jsx';
    import SignUpPage from './containers/SignUpPage.jsx';
    import Auth from './modules/Auth';
    
    
    const routes = {
      // base component (wrapper for the whole application).
      component: Base,
      childRoutes: [
    
        {
          path: '/',
          getComponent: (location, callback) => {
            if (Auth.isUserAuthenticated()) {
              callback(null, DashboardPage);
            } else {
              callback(null, HomePage);
            }
          }
        },
    
        {
          path: '/login',
          component: LoginPage
        },
    
        {
          path: '/signup',
          component: SignUpPage
        },
    
        {
          path: '/logout',
          onEnter: (nextState, replace) => {
            Auth.deauthenticateUser();
    
            // change the current URL to /
            replace('/');
          }
        }
    
      ]
    };
    
    export default routes;