Published on

5 - React Router (Navigation): Building Scalable Applications with Dynamic and Protected Routes

Authors
  • avatar
    Name
    Jonas de Oliveira
    Twitter

In today's web development landscape, delivering smooth and secure navigation is essential for providing a high-quality user experience. React Router, through the react-router-dom package, is an indispensable tool for managing routes in a React application. In this article, we'll explore how to implement navigation using dynamic and protected routes, demonstrating practices that add robustness and scalability to your projects—a key differentiator that will catch recruiters' attention.

React Router and react-router-dom: An Overview

React Router is a library that allows you to create and manage navigation within React applications. By using react-router-dom, you can define routes, create links between them, and control the rendering of components based on the current URL. This approach improves user experience by providing smooth transitions between pages and sections.

Installing React Router

To get started, install the package:

npm install react-router-dom

With React Router, you can create a route structure that maps URLs to specific components, making your code more organized and maintainable.

Dynamic Routes

Dynamic routes allow you to create URLs that vary according to the parameters passed, making your application more flexible and adaptable to different contexts. A classic example is a user profile page, where the user ID is part of the URL.

Example of Dynamic Routes

Imagine you want to create a route to display a user's details. Here’s how to implement it with react-router-dom:

import React from 'react';
import { BrowserRouter, Routes, Route, useParams } from 'react-router-dom';

// Component that displays a user profile based on a dynamic URL parameter.
const UserProfile: React.FC = () => {
  // Extract the 'id' parameter from the URL using the useParams hook.
  const { id } = useParams<{ id: string }>();
  
  // Render the user profile using the extracted 'id'.
  return <div>User Profile: {id}</div>;
};

const App: React.FC = () => {
  return (
    // BrowserRouter enables routing in the application.
    <BrowserRouter>
      {/* Routes container holds all the defined routes */}
      <Routes>
        {/* Define a dynamic route that captures the 'id' from the URL */}
        <Route path="/user/:id" element={<UserProfile />} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

In this example, the route /user/:id captures the id parameter from the URL, allowing the UserProfile component to display information specific to that value.

Protected Routes

Protected routes are essential for ensuring that only authenticated users can access certain parts of your application, such as profile pages, admin panels, or any restricted area. This mechanism is fundamental for application security.

Example of a Protected Route

To implement a protected route, you can create a component that checks if a user is authenticated and redirects to the login page if they are not.

import React from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';

// Define the props for the ProtectedRoute component.
interface ProtectedRouteProps {
  isAuthenticated: boolean; // Indicates if the user is authenticated.
  children: JSX.Element;    // The component to render if authenticated.
}

// Component that checks if a user is authenticated before rendering its child component.
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ isAuthenticated, children }) => {
  // If the user is not authenticated, redirect to the login page.
  if (!isAuthenticated) {
    return <Navigate to="/login" replace />;
  }
  // Otherwise, render the protected component.
  return children;
};

// Simple component representing an admin dashboard.
const Dashboard: React.FC = () => <h2>Admin Dashboard</h2>;

// Simple component representing a login page.
const Login: React.FC = () => <h2>Login Page</h2>;

const App: React.FC = () => {
  // Simulate authentication status; set to 'true' to allow access to protected routes.
  const isAuthenticated = false;

  return (
    // BrowserRouter enables routing within the application.
    <BrowserRouter>
      {/* Define application routes */}
      <Routes>
        {/* Public route accessible without authentication */}
        <Route path="/login" element={<Login />} />
        {/* Protected route wrapped in ProtectedRoute to enforce authentication */}
        <Route
          path="/dashboard"
          element={
            <ProtectedRoute isAuthenticated={isAuthenticated}>
              <Dashboard />
            </ProtectedRoute>
          }
        />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

In the example above, the ProtectedRoute component checks whether the user is authenticated. If not, the user is redirected to the login page. This pattern ensures that restricted areas of the application are accessible only to authorized users.

Final Thoughts

Integrating React Router into your application with react-router-dom is a strategic step in creating modern and efficient navigation experiences. The ability to implement dynamic routes enables you to create flexible URLs that adapt to the content, while protected routes reinforce security by ensuring that only authorized users can access sensitive areas.