Justas Dambrauskas
Justas Dambrauskas

Reputation: 73

React Router with Private Route render blank page

All related topics readed, but answer still not found

Hello everyone,

I have a bug in my code and as always I can't find it, so please help me to find the way to make it work.

I have create-react-app where I'm trying to add user authentication. The tutorial I'm looking in: http://jasonwatmore.com/post/2018/09/11/react-basic-http-authentication-tutorial-example

Problem: When I'm logged in I'm seeing "Dashboard" (exact) component, everything is OK. But then I'm clicking on other Link, like 'orders' and etc. I'm getting blank page rendered. No errors on console.

Let's begin from the start.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

import { configureFakeBackend } from './_helpers/fake-backend';
configureFakeBackend();

ReactDOM.render((
      <App />
), document.getElementById('root')); 

App.js file

import React, { Component } from 'react';
import './App.scss';
import MainContent from './components/MainContent.jsx';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { PrivateRoute } from './components/PrivateRoute';
import { LoginPage } from './LoginPage/LoginPage';


class App extends Component {
  render() {
    return (
            <Router>
              <Switch>
                <PrivateRoute exact path="/" component={MainContent} />
                <Route path="/login" component={LoginPage} />
              </Switch>
            </Router>
    );
  }
}

export default App;

PrivateRoute.jsx

import React from 'react';
import { Route, Redirect } from 'react-router-dom';

export const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        localStorage.getItem('user')
            ? <Component {...props} />
            : <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
    )} />
)

MainContent.jsx

import React, { Component } from 'react';
import Sidebar from './Sidebar.jsx';
import Header from './Header.jsx';
import Main from './Main.jsx';
import { userService } from '../_services/user.service';
import { Link } from 'react-router-dom';

class MainContent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            user: {},
            users: []
        };
    }
    componentDidMount() {
        this.setState({ 
            user: JSON.parse(localStorage.getItem('user')),
            users: { loading: true }
        });
        userService.getAll().then(users => this.setState({ users }));
    }
  render() {
    const { user, users } = this.state;
    return (

      <React.Fragment>
      <h1>Hi {user.firstName}!</h1>
      {users.loading && <em>Loading users...</em>}
      {users.length &&
          <ul>
              {users.map((user, index) =>
                  <li key={user.id}>
                      {user.firstName + ' ' + user.lastName}
                  </li>
              )}
          </ul>
      }
      <p>
          <Link to="/login">Logout</Link>
      </p>
        <Sidebar />
        <div id="flexing">
            <Header />
            <Main />
          </div>
      </React.Fragment>
    );
  }
}

export default MainContent;

And at least: Main.jsx

import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Dashboard from './Dashboard';
import Orders from './Orders';
import Routes from './Routes';
import Drivers from './Drivers';
import Settings from './Settings';

const Main = () => (
  <main>
    <Switch>
      <Route exact path='/' component={Dashboard}/>
      <Route path='/orders' component={Orders}/>
      <Route path='/routes' component={Routes}/>
      <Route path='/drivers' component={Drivers}/>
      <Route path='/settings' component={Settings}/>
    </Switch>
  </main>
);

export default Main;

So the Dashboard component will render good, but others render like blank page. Please help to fix it. Waiting for reply.

Justas

Upvotes: 2

Views: 1444

Answers (1)

ZekeDroid
ZekeDroid

Reputation: 7209

Right so what's happening is that those routes in Main.js are rendered ONLY when App.js renders it. That is, when the path is /, Main.js is rendered. When it's something else, Main.js isn't rendered and so that Switch component is never hit.

To solve it, you should either remove Main.js and put all of these routes in the top level (you can have two Switch components in App.js if that helps), or set the path in App.js (for MainComponent) to include all of these. The former is cleaner as the latter could get complicated.

To see that this is the problem, add a default route to App.js and you'll see that the "blank" page you're seeing is because nothing was matching at that level; to set a default, have the path match on *.

Upvotes: 1

Related Questions