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
- Go to this URL: https://github.com/muditchoudhary/my-demo-app
- Fork and then clone the project locally
-
cd my-demo-app
- Run
npm install
- Will download the necessary packages - 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;
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 />;
}
};
<>
<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>
</>
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 />;
}
};
<Route element={<AuthRedirect />}>
<Route path="/sign-in" element={<SignInPage />}/>
</Route>
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
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)