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'
}
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;
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;
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;
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)
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!