DEV Community

Cover image for How to Protect Routes With React Router v6 (Old APIs)
Mudit Choudhary
Mudit Choudhary

Posted on

How to Protect Routes With React Router v6 (Old APIs)

Table of Content

  • Getting Started
  • Cloning and setting up the project
  • Creating paths with React Router and making components
  • Protecting the Dashboard path and preventing accessing the sign-in and sign-up path
  • Demo Video
  • Conclusion

Getting Started

Hey folks! In this blog, I'll share how to create a protected route with React Router 6.

I have a Demo app, which has three paths, the home, the sign-in, and the dashboard path. The dashboard will be the protected path that only the authenticated user can access. If a non-authenticated user tries to access it they will navigate to the sign-in path.

I have initialized my project with the Vite React template. I have provided the source code below, go to that URL and clone the project if you want to play around with the code.

Cloning and setting up the project

  1. Go to this URL: https://github.com/muditchoudhary/my-demo-app
  2. Fork and then clone the project locally
  3. cd my-demo-app
  4. Run npm install - Will download the necessary packages
  5. Then start the server npm run dev - will run the dev server

Creating paths with React Router and making the four pages

I have created one RootLayout which will be the parent layout for all of the other 3 route pages. Then I created three routes and pages.

import { Routes, Route, BrowserRouter } from "react-router-dom";

import { HomePage } from "./pages/HomePage";
import { RootLayout } from "./layouts/RootLayout";
import { SignInPage } from "./pages/SignInPage";
import { DashBoardPage } from "./pages/DashBoardPage";

function App() {
    return (
        <>
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<RootLayout />}>
                        <Route index element={<HomePage />} />
                        <Route path="/sign-in" element={<SignInPage />} />
                        <Route path="/dashboard" element={<DashBoardPage />} />
                    </Route>
                </Routes>
            </BrowserRouter>
        </>
    );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

The code of pages is very simple, HomePage has a h1 heading. The SignInPage has a form with an onSubmit handler that will call the signIn method to store user details locally in the LocalStorage. And the DashBoardPage has an h1 heading.

Protecting the Dashboard path and preventing accessing the sign-in path after sign-in

Currently even without sign-in the user can access the /dashboard path. And after the sign-in, they can access the /sign-in path. This is bad user experience. We want to prevent the user from accessing the /dasboard path without sign-in and prevent accessing the /sign-in path after sign-in.

To do this we will create a wrapper router component that will check if the user has signed in when visiting the /dashborad. We will create another wrapper component that will check if the user has already signed in and then prevent accessing /sign-in path.

Protecting the DashBoard

In the App.jsx I have created an AuthGuard component which acts as a wrapper or parent element for the /dashboard path. It gets the user object from the LocalStorage, and checks if the user is null or not. If null it navigates to the sign-in path along with the form state to remember where the user wants to go. So that after sign-in the user is redirected to that path instead of home.

const AuthGuard = () => {
    const user = JSON.parse(localStorage.getItem("user"));
    const location = useLocation();

    if (user === null) {
        return <Navigate to="/sign-in" state={{ from: location }} replace />;
    } else {
        <Outlet />;
    }
};
Enter fullscreen mode Exit fullscreen mode
<>
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<RootLayout />}>
                        <Route index element={<HomePage />} />
                        <Route path="/sign-in" element={<SignInPage />} />
                        <Route element={<AuthGuard />}>
                            <Route
                                path="/dashboard"
                                element={<DashBoardPage />}
                            />
                        </Route>
                    </Route>
                </Routes>
            </BrowserRouter>
        </>
Enter fullscreen mode Exit fullscreen mode

Preventing accessing sign-in path after sign-in

After the the user has signed in we do not want the user to be able to access the sign-in path. To prevent this I created an AuthRedirect component wrapper which gets the user from LocalStorage and if it is not null navigates the user to the home path. And If it is null it lets the sign-in component render.

const AuthRedirect = () => {
    const user = JSON.parse(localStorage.getItem("user"));
    if (user === null) {
        return <Outlet />;
    } else {
        return <Navigate to={"/"} replace />;
    }
};
Enter fullscreen mode Exit fullscreen mode
<Route element={<AuthRedirect />}>
    <Route path="/sign-in" element={<SignInPage />}/>
</Route>

Enter fullscreen mode Exit fullscreen mode

Note: Navigating the user to the home path is not a good user experience. Currently, I do not know how to remember the previous path from which the user goes to the sign-in path. For example. When the user is in the /dashboard path instead of navigating to the home path we should navigate back to the dashboard path.

If you know how to do it, please tell me in the comments. Otherwise, I'll update the blog when I find and understand.

Demo Video

https://imgur.com/a/oENS6ty

Conclusion

That is how we prevent the user from navigating the protected route in the front end. In a real application or project, you will not directly access the LocalStorage. Instead, you will possibly have a global context that first checks the user in LocalStorage, and when the user signs in it update that context.

Thank you! If you like it make sure to give a like and share it if you want. If you have any doubts you can ask me in the comments.

Here are my socials you can connect with me if you would like to:

X (Twitter): https://twitter.com/mudit__01
Github: https://github.com/muditchoudhary
Linkedin: https://www.linkedin.com/in/mudit-choudhary-a87243228/

Top comments (0)