DEV Community

Cover image for Private, Public and Restricted routes in React
Karan Pratap Singh
Karan Pratap Singh

Posted on

Private, Public and Restricted routes in React

In this article, we'll be implementing private, public, and restricted routes. I'll be using React Router, but the idea should be similar across other routing libraries.

Let's take an example of the following components:

Home: or a similar public route that everyone can access.

Login: is a restricted route, which means it should only be accessible by unauthenticated users because it doesn't make much sense if an authenticated user can access login/signup pages.

Dashboard: is a private route that should only be accessed by authenticated users.

Let's consider the following abstractions before we start with the code:

isAuthenticated which tells us if the user is authenticated or not.

ROUTES can be an enum to access our routes.

enum ROUTES {
  HOME = '/',
  LOGIN = '/login'
  DASHBOARD = '/dashboard'
}
Enter fullscreen mode Exit fullscreen mode

Private Route

The idea here is to render our component if the user is authenticated or redirect the user to login if not authenticated.

import React from 'react';
import { Route, Redirect, RouteProps } from 'react-router-dom';
import { ROUTES } from '../constants';
import { isAuthenticated } from '../auth.utils';

function PrivateRoute(props: RouteProps): React.ReactElement {
    const { component: Component, ...rest } = props;

    const render = props => {
        if (!isAuthenticated) {
            return <Redirect to={ROUTES.LOGIN} />;
        }

        return <Component {...props} />;
    };

    return <Route {...rest} render={render} />;
}

export default PrivateRoute;
Enter fullscreen mode Exit fullscreen mode

Public and Restricted Routes

The Route component from react-router is public by default but we can build upon it to make it restricted.

We can add a restricted prop with a default value of false and use the condition if the user is authenticated and the route is restricted, then we redirect the user back to the Dashboard component.

import React from 'react';
import { Route, Redirect, RouteProps } from 'react-router-dom';
import { ROUTES } from '../constants';
import { isAuthenticated } from '../auth.utils';

interface PublicRouteProps {
    restricted?: boolean;
}

function PublicRoute(props: PublicRouteProps & RouteProps): React.ReactElement {
    const { component: Component, restricted = false, ...rest } = props;

    const render = props => {
        if (isAuthenticated && restricted) {
            return <Redirect to={ROUTES.DASHBOARD} />;
        }

        return <Component {...props} />;
    };

    return <Route {...rest} render={render} />;
}

export default PublicRoute;
Enter fullscreen mode Exit fullscreen mode

Putting it together

Finally, let's declare all the routes in our App.tsx component and see how our routing looks now.

import React from 'react';
import { BrowserRouter, Switch } from 'react-router-dom';
import { ROUTES } from './constants';
import { Home, Dashboard, Login } from './pages';
import { PrivateRoute, PublicRoute } from './components';

function App(): React.ReactElement {
    return (
        <BrowserRouter>
            <Switch>
                <PublicRoute component={Home} path={ROUTES.HOME} exact />
                <PublicRoute restricted component={Login} path={ROUTES.LOGIN} exact />
                <PrivateRoute component={Dashboard} path={ROUTES.DASHBOARD} exact />
            </Switch>
        </BrowserRouter>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Hopefully, this gave you an insight into how we can organize private and protected routes.

Feel free to reach out to me on Twitter (@karan_6864) if you face any issues.

Happy Coding 🎉

Top comments (1)

Collapse
 
kristjanreinhold profile image
Kristjan

Thanks! Used your implementation. For me i had to tweak it because i have a public design landing page and logged in admin dashboard.

Had to remove exact from Public route - so it would reDirect into the Home.

And within my Home - had to implement Switch for routes public routes

Routes.map...
if (prop.layout === PUBLIC_ROUTE) {
// Exact in here!