0

I want to restrict parts of my app to logged in users only. I have this working using the code below.

However, previously I was making use of the Switch router to send users to a 404 page when no matching routes are found.

For some reason since I adding the EnsureLoggedIn component to App.jsx the user is never redirected to the 404 page.

Test: Random path entered in URL. Should route to the 404 page.

  • isLoggedIn=false : The user gets directed to the /login page.
  • isLoggedIn=true : No matching route is found and the page container is rendered empty.

I'd expect the switch router to ignore what's nested inside EnsureLoggedIn since none of the routes match, then render the 404.

Hoping someone with a bit more React experience can steer me on this.

App.jsx

<BrowserRouter>
  <Header/>
  <Switch>
   <Route exact path="/" component={HomePage}/>
   <Route exact path="/someotherpage" component={SomeOtherPage}/>
   <EnsureLoggedIn>
     <Route exact path="/dashboard" component={Dashboard}/>
   </EnsureLoggedIn>
   <Route component={Error404Page}/>
  </Switch>
  <Footer/>
</BrowserRouter>

EnsureLoggedIn.jsx

 class EnsureLoggedIn extends Component {

   constructor(props) {
     super(props);
     this.state = {isLoggedIn: false};
   }

   render() {
     const isLoggedIn = this.state.isLoggedIn;
     if (isLoggedIn) {
       return this.props.children
     } else {
        return ( <Redirect to="/login" /> );
     }
   }
 }

2 Answers 2

2

<Switch> renders the first matching child <Route> - however your <EnsureLoggedIn> component gets rendered anyway and circumvents the <Switch> exclusivity by explicitly rendering its children. I'm not sure this kind of hierarchy is supported.

Consider having a <LoggedInEnsuringDashboard> or similar and putting that straight into the Router without the nesting.

Edit:

Something along the lines of:

<BrowserRouter>
  <Header/>
  <Switch>
   <Route exact path="/" component={HomePage}/>
   <Route exact path="/someotherpage" component={SomeOtherPage}/>
   <Route exact path="/dashboard" component={LoggedInEnsuringDashboard}/>
   <Route component={Error404Page}/>
  </Switch>
  <Footer/>
</BrowserRouter>

And

class LoggedInEnsuringDashboard extends Component {

   constructor(props) {
     super(props);
   }

   render() {
     if (this.props.isLoggedIn) {
       return <Dashboard>
     } else {
        return <Redirect to="/login" />
     }
   }
 }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I've also found that react-router v4 doesn't like nested routes. I'd based my approach on an out of date tutorial.
0

Just to provide another approach which I ended up using.

This involves creating a container called UserArea which has all the admin only pages listed as subcontainers.

Then in the render function, the following ensures that any url which begins with /user-area will be redirected to the login page if the user is not logged in.

this.isLoggedIn() ? (<UserArea />) : (<Redirect to="/login" />) )

App.jsx

<BrowserRouter>
  <Header/>
  <Switch>
   <Route exact path="/" component={HomePage}/>
   <Route exact path="/someotherpage" component={SomeOtherPage}/>
   <Route exact path="/login" component={LoginPage}/>
   <Route path="/user-area" render={ ()=>(this.isLoggedIn() ? (<UserArea />) : (<Redirect to="/login" />) )} />
   <Route component={Error404Page}/>
  </Switch>
  <Footer/>
</BrowserRouter>

UserArea.jsx

<BrowserRouter>
  <main className="ks-main-content ks-container__user-area">
    <UserAreaHeader />
      <Switch>
      <Route exact path="/user-area/dashboard" component={UserAreaDashboardPage}/>
      <Route exact path="/user-area/profile" component={UserAreaProfile}/>
      <Route component={Error404Page} />
    </Switch>
  </main>
</BrowserRouter>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.