In this article, we’ll learn how to implement protected routes in a React.js application. Protected routes ensure that certain pages are accessible only after the user has successfully authenticated. If an unauthenticated user tries to access these pages, they are redirected to the login page.
Let’s consider a simple example application where we’ll implement protected routes over existing routes to safeguard access to specific components.
Defining the Application Routes
In this example, we have three routes rendered using react-router-dom.
- Home: a protected route only accessible to authenticated users.
- Profile: another protected route restricted to logged-in users.
- Login: an open route accessible to everyone for logging into the app.
Our goal is to ensure that the Home and Profile components render only after the user has been authenticated. If the user is not authenticated, they’ll automatically be redirected to the login page.
Creating the Protected Route Component
To implement route protection, we’ll create a new component called ProtectedRoutes.jsx. This component will wrap any route that needs to be protected. By using a single component for protection, we can nest the protected routes within it, running an authentication check before rendering any of these pages.
Here’s how to build the ProtectedRoutes.jsx component.
- Define the Authentication State: For simplicity, let’s assume we have a variable user that stores the authentication status. Initially, the user is set to null to represent an unauthenticated state. When a user logs in, the user is updated to true.
- Rendering Logic: Within ProtectedRoutes.jsx, we’ll use a conditional statement to render the child routes. If the user is authenticated (i.e., true), we’ll allow the child routes to render using <Outlet />, a React Router component that renders nested routes. If a user is not authenticated, we’ll redirect to the login page using Navigate from react-router-dom.
Here’s the code for ProtectedRoutes.jsx.
What is <Outlet /> in React Router?
The <Outlet /> component from react-router-dom is used within a parent route to define where a child route element should be rendered. Here’s what you need to know about <Outlet />.
- Rendering: <Outlet /> renders the next matching child route. If there’s no matching child route, it renders null.
- Props: <Outlet /> doesn’t take any props.
- Flexible Rendering: <Outlet /> can be rendered at any point within a route’s component tree.
- Code Reuse: It helps reduce repetition in the component structure.
- Layout Building: <Outlet /> is useful for creating consistent layouts, like headers and sidebars, which can wrap all nested pages.
Integrating Protected Routes in App.jsx
After creating ProtectedRoutes.jsx, we can integrate it into App.jsx by wrapping the protected routes. Here’s an example of how to set up App.jsx with protected and public routes.
In this setup,
- The /login route is publicly accessible.
- Both /home and /profile routes are wrapped inside ProtectedRoutes. If user is authenticated, they will render; otherwise, the user will be redirected to /login.
Summary
Using a ProtectedRoutes component in a React application is an effective way to guard certain routes from unauthenticated users. With the help of react-router-dom and components like <Outlet /> and Navigate, we can control access to routes and enforce authentication without adding repetitive checks within each protected component.
This pattern is not only clean and scalable but also keeps your routing logic organized and efficient. For more complex scenarios, such as roles-based access or multiple authentication layers, this foundational setup can be expanded to meet your application’s needs.