DEV Community

Cover image for Protected Routes in React
sundarbadagala
sundarbadagala

Posted on • Updated on

Protected Routes in React

INTRO 🔊

As a frontend developer, it is very important to know that routing and particularly private routing for user authentication. For example some applications are public i.e any one can see and modify content in it, but some other applications are not allowed all the users to modify the content inside the application like posting new data, deleting and modifying the data etc..., For that we have to use protected routes in ReactJS.

In this post we will discuss how to create protected routes in ReactJS in simple and efficient way without any confusion.🔥

APPROACH 🔊

I hope you people already created ReactJS application. Otherwise please follow this link to create react application

📌 NOTE: To handle protected routes in ReactJS, we have to install library react-router-dom

npm i react-router-dom
Enter fullscreen mode Exit fullscreen mode

react router dom is the famous library which helps to routing in ReactJs.

After install the library check the package.json file whether that library was installed or not.

📌 NOTE: This routing method will works only the library react-router-dom having the version >= 6 not for the version <= 5

Now we have to create one helper file useAuth to check whether a token is preset or not.

📌 NOTE: Token is specific key (response) provided from the backend when user logged in successfully. By using token we can check whether the user is logged in or logged out.

//useAuth.js

export const useAuth = () => {
    //getting token from local storage
    const user = localStorage.getItem('token')
    //checking whether token is preset or not
    if (user) {
        return true;
    } else {
        return false
    }
};
Enter fullscreen mode Exit fullscreen mode

Now we have to create two files named privateRoute and publicRoute. privateRoute file will execute when the user is logged in state and publicRoute file will execute when the user is logged out state.

//privateRoutes.js

import { Outlet, Navigate } from 'react-router-dom'
import { useAuth } from './useAuth'

function PrivateRoutes() {
    const token = useAuth()
    return token ? <Outlet /> : <Navigate to='/login' />
}

export default PrivateRoutes
Enter fullscreen mode Exit fullscreen mode
//publicRoutes.js

import { Outlet, Navigate } from 'react-router-dom'
import { useAuth } from './useAuth'

function PublicRoutes() {
    const token = useAuth()
    return token ? <Navigate to='/' /> : <Outlet />
}

export default PublicRoutes
Enter fullscreen mode Exit fullscreen mode

The routing setup completed successfully. 🎉


Now we have to use this setup in our application to handle private routing. 🔥

//App.js

//importing from react-router-dom libary
import { Routes, Route } from 'react-router-dom'
//importing previously created privateRoute.js file
import PrivateRoutes from "./privateRoutes"
//importing previously created publicRoute.js file
import PublicRoutes from './publicRoutes'
//let's import some private components
import Home from './home'
import ErrorComp from './error'
//let's import some public components
import Login from './login'

function App() {
  return (
    <Routes>
      <Route element={<PrivateRoutes />}>
        <Route element={<Home />} path='/' />
        <Route element={<ErrorComp />} path='*' />
      </Route>
      <Route element={<PublicRoutes />}>
        <Route element={<Login />} path='/login' />
      </Route>
    </Routes>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Finally the protected routes in ReactJS completed successfully. 🎉 🎉

Now we can check those private routes and public routes by providing the token (let's take any string) manually in chrome devtools->inspect->application.


Otherwise we can create login and home files to handle the routing in client side. 🚀

Create login (public component) page to log the user in and redirect to home (private component) page after setting the token in local storage successfully (the app can redirect to home when only token is preset in local storage).

//login.js

import { useNavigate } from 'react-router-dom'

function Login() {
    const navigate = useNavigate()
    const handleLogin=()=>{
    const res = {**login api call***}
    const token = res.data.token //let's take some string 'dev' as token
    localStorage.setItem('token', JSON.stringify(token))
    navigate('/')
    }
    return (
        <>
          <button onClick={handleLogin}>Login</button>
        </>
    )
}

export default Login
Enter fullscreen mode Exit fullscreen mode

Create home (private component) page to view the user personal details and to log the user out.

//home.js

import {useNavigate} from 'react-router-dom'

function Home() {
    const navigate = useNavigate()
    const handleLogout = () => {
        localStorage.removeItem('token')
        navigate('/login')
    }
    return (
        <>
            <button onClick={handleLogout}>log out</button>
            <div>home page</div>
            <div>hello user</div>
        </>
    )
}

export default Home
Enter fullscreen mode Exit fullscreen mode

Create error page (optional) to display while doing wrong routing.

//error.js

function Error() {
  return (
    <>
      this is error page
    </>
  )
}

export default Error
Enter fullscreen mode Exit fullscreen mode

Finally the whole routing setup and checking done successfully 🎉 🎉 🎉

📌 NOTE: In the same way we can create multiple components and add them in to App.js page.

SOURCE CODE 🔊

For the source code, you can check my git hub link here 💡

CONCLUSION 🔊

I hope you people understand, how to setup protected routes in ReactJS by using React Router Dom having version 6 and above.
We will meet next time with another post. 🔥

Peace 🙂

Top comments (2)

Collapse
 
nicolasdanelon profile image
Nicolás Danelón

There is a huge security concern when storing tokens or sensitive data in localStorage is not recommended due to potential security vulnerabilities, primarily from XSS attacks. Instead, consider using HttpOnly cookies or other secure methods.

please check this code simplification, the if-else structure can be simplified:

export const useAuth = () => {
    const token = localStorage.getItem('token');
    return !!token; // The double '!!' converts a truthy or falsy value to its boolean equivalent.
};
Enter fullscreen mode Exit fullscreen mode

I want to point out functional Naming. The name useAuth suggests it might be a React hook, especially when prefixed with use. However, this function doesnt use any hook.

Please read more code before writing articles about coding

Collapse
 
sundarbadagala081 profile image
sundarbadagala

Hi @nicolasdanelon, First of all, thank you for your valuable suggestions.
Yeah, you are right, HttpOnly cookies are better than local storage I accept that but here I used local storage for basic authentication,
I intentionally mentioned that the name of the helper was useAuth. Please visit my previous post about the useDebounce hook. There I clearly wrote hook and helper.
useDebounce
The code in useAuth is also intentionally written using the if else condition for easy understanding even for beginners.