aditya kumar
aditya kumar

Reputation: 3023

What is the best way to make private route in reactjs

I made a private route in my app basically all the route in my app is private. So to make Private route I added a state isAuthenticated which is false by default but when user login in it becomes true. So on this isAuthenticated state I implemented a condition in private route component. But the problem with this is when user is logged in and refresh the page. I get redirect to / home page. I don't want that.

I am use token authentication here.

Here is my PrivateRoute.js

import React from "react";
import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";

const PrivateRoute = ({ isAuthenticated, component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) =>
      isAuthenticated ? <Component {...props} /> : <Redirect to="/" />
    }
  />
);

function mapStateToProps(state) {
  return {
    isAuthenticated: state.user.isAuthenticated,
  };
}

export default connect(mapStateToProps)(PrivateRoute);

Upvotes: 1

Views: 133

Answers (2)

pawel
pawel

Reputation: 36965

If you validate the token against a server (which you should) then it's an asynchronous operation and isAuthenticated will be falsy initially, causing the redirect on refresh.

You one way around this is an isAuthenticating state, e.g.

import React from "react";
import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";

const PrivateRoute = ({ isAuthenticated, isAuthenticating, component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) => {
      if( isAuthenticating ){ return <Spinner /> }
      return isAuthenticated ? <Component {...props} /> : <Redirect to="/" />
      }
    }
  />
);

function mapStateToProps(state) {
  return {
    isAuthenticated: state.user.isAuthenticated,
    isAuthenticating: state.authentication.inProgress
  };
}

export default connect(mapStateToProps)(PrivateRoute);

isAuthenticating should be true by default then set to false when the server response is received and the user.isAuthenticated state is known.

Upvotes: 1

Dominik
Dominik

Reputation: 437

If all your routes when authenticated are private you can also just skip the autentication by route and use following

import PrivateApp from './PrivateApp'
import PublicApp from './PublicApp'


function App() {
   // set isAuthenticated dynamically
   const isAuthenticated = true

   return isAuthenticated ? <PrivateApp /> : <PublicApp />
}

That way you do not need to think for each route if it is authenticated or not and can just define it once and depending on that it will render your private or public app. Within those apps you can then use the router normally and do not need to think who can access which route.

Upvotes: 1

Related Questions