Why Do We Need Route Guards?
Route guards are crucial for maintaining the security and integrity of your application. Here’s why you should use them:
Protect Sensitive Information: Route guards prevent unauthorized users from accessing restricted areas containing sensitive data.
Prevent Confusion: They help redirect unauthenticated users to appropriate pages, like the login page.
Role-Based Access Control: You can implement role-based access with route guards, allowing different users (e.g., admins, regular users) to access different parts of the application.
Steps to Implement Route Guards
Let’s walk through the steps to add route guards in React using React Router v6, which is the recommended version for implementing route guards effectively.
Step 1: Public & Private Components
Create components for public and protected routes:
// PublicPage.jsx
const PublicPage = () => {
return <p>This is a public route.</p>;
};
export default PublicPage;
// PrivatePage.jsx
const PrivatePage = () => {
return <div>This is a protected route.</div>;
};
export default PrivatePage;
Step 2: Create Auth Context Provider
Set up a global context to manage authentication:
// AuthenticationProvider.jsx
import { createContext, useState } from "react";
export const AuthenticationContext = createContext({});
export function AuthenticationProvider({ children }) {
const [userAuth, setUserAuth] = useState(null); // Initialize to null for unauthenticated state
return (
<AuthenticationContext.Provider value={{ userAuth, setUserAuth }}>
{children}
</AuthenticationContext.Provider>
);
}
export default AuthenticationProvider;
The AuthenticationProvider
component wraps the app and provides authentication data to any component that needs it.
Step 3: Custom Hook for Authentication
Create a custom hook to retrieve and update the authentication state:
// useAuthentication.jsx
import { useContext } from "react";
import { AuthenticationContext } from "./AuthenticationProvider";
const useAuthentication = () => {
return useContext(AuthenticationContext);
};
export default useAuthentication;
This hook allows us to easily access the authentication context from any part of the app.
Step 4: Guard Component
This component protects routes and redirects users if they are not authenticated:
// ProtectRoute.jsx
import { Navigate, Outlet } from "react-router-dom";
import useAuthentication from "./useAuthentication";
const ProtectRoute = () => {
const { userAuth } = useAuthentication();
return userAuth ? <Outlet /> : <Navigate to="/" />;
};
export default ProtectRoute;
If the user is authenticated, the component renders its children (<Outlet />
), otherwise, it navigates to the home page.
Step 5: Implementing Routes
Finally, set up public and private routes using React Router:
// AppContainer.jsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import AuthenticationProvider from "./AuthenticationProvider";
import PublicPage from "./PublicPage";
import PrivatePage from "./PrivatePage";
import ProtectRoute from "./ProtectRoute";
const AppContainer = () => {
return (
<div className="App">
<BrowserRouter>
<AuthenticationProvider>
<Routes>
<Route path="/" element={<PublicPage />} />
<Route element={<ProtectRoute />}>
<Route path="/dashboard" element={<PrivatePage />} />
</Route>
</Routes>
</AuthenticationProvider>
</BrowserRouter>
</div>
);
};
export default AppContainer;
In this example, /dashboard
is a protected route and can only be accessed by authenticated users.
Final Thoughts
Using route guards in React ensures that only authorized users can access certain parts of your application. By combining React Router with context and custom hooks, we can easily secure routes and manage user access.
Additional Considerations
Persisting Authentication State: To maintain the authentication state across page refreshes, consider using
localStorage
or cookies to store the user's authentication token. This way, you can check the token on app load to determine the user's authentication status.Server-Side Validation: Remember that client-side checks alone are not sufficient for security. Always validate user permissions on the server side to ensure that users cannot access restricted resources.
If you found this blog helpful and want to support, feel free to buy me a coffee!
References
Upstatement. (2024). React Router Guards.
Amrita Padhy. (2024). All about router guards in React JS.
Netcetera. (2024). How to create guarded routes for your React-App.
UI.dev. (2024). Protected Routes and Authentication with React Router.
Technostacks. (2024). 33 React Best Practices For 2024.
This updated blog post incorporates the latest practices for implementing route guards in React, ensuring that it is relevant for developers in 2024.
Citations: [1] https://github.com/Upstatement/react-router-guards [2] https://dev.to/amritapadhy/all-about-router-guards-in-react-js-50b6 [3] https://blog.netcetera.com/how-to-create-guarded-routes-for-your-react-app-d2fe7c7b6122?gi=36bc81efa897 [4] https://www.angularminds.com/blog/protected-routes-in-react-router-authentication-and-authorization [5] https://www.reddit.com/r/reactjs/comments/1cck2zd/need_help_to_implement_routeguardauthguard_on_my/ [6] https://ui.dev/react-router-protected-routes-authentication [7] https://stackoverflow.com/questions/31084779/how-to-restrict-access-to-routes-in-react-router [8] https://technostacks.com/blog/react-best-practices/