Computer scienceFrontendReactReact Router

Nested and dynamic routes

10 minutes read

In modern web development, routing plays a critical role in navigating between different views or components within an application. React.js, with its component-based architecture, offers a robust way to manage routing, especially when it comes to nested and dynamic routes. In this topic, you will delve into the concepts of nested and dynamic routing in React.js, understand their importance, and how to implement them to create feature-rich and user-friendly applications.

Understanding nested routes

Nested routing, also known as child routing, involves defining routes within other routes. This hierarchical approach to routing reflects the component structure of the application and is useful for creating complex user interfaces with multiple layers of navigation. For example, imagine an e-commerce application that has a main product component. Within this component, there might be nested routes for individual product categories, such as electronics, clothing, and books. Each category could further contain nested routes for specific items.

Here's a simple example in App.jsx of nested routing in a React application using React Router:

import {
  BrowserRouter as Router,
  Route,
  Routes,
  Outlet,
} from "react-router-dom";
import Home from "./Home";
import About from "./About";
import Dashboard from "./Dashboard";
import Settings from "./Settings";
import Profile from "./Profile";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/dashboard" element={<DashboardOutlet />}>
          <Route index element={<Dashboard />} />
          <Route path="profile" element={<Profile />} />
          <Route path="settings" element={<Settings />} />
        </Route>
      </Routes>
    </Router>
  );
}

function DashboardOutlet() {
  return (
    <>
      <Outlet />
    </>
  );
}
export default App;
  • <Route path="/dashboard" element={<DashboardOutlet />}>: This is the parent route. It matches the URL path /dashboard and renders the DashboardOutlet component. The DashboardOutlet component is responsible for rendering the nested routes' components.

  • <Route index element={<Dashboard />} />: This is a nested route. The index prop indicates that this route corresponds to the base path of its parent route, which is /dashboard in this case. If a user navigates to /dashboard, the Dashboard component will render inside the DashboardOutlet component.

Index page of nested routing

  • Route path="settings" element={<Settings />} />: Similarly, this nested route matches the URL path /dashboard/settings. When a user navigates to this path, the Settings component will render inside the DashboardOutlet component.

Settings page from nested routing

  • <Route path="profile" element={<Profile />} />: This is another nested route. It matches the URL path /dashboard/profile. When a user navigates to this path, the Profile component will render inside the DashboardOutlet component.

Profile page from nested routing

  • DashboardOutlet is a functional component that returns an Outlet. The Outlet is a special component provided by React-router that renders the appropriate child route component based on the current URL. In this example, if the URL is /dashboard/profile, the Outlet will render the Profile component.

The DashboardOutlet component acts as a placeholder for these nested components, enabling the appropriate content to be rendered based on the URL path.

Nested routing is invaluable for organizing subsections within an application, such as a dashboard with distinct views for a user's profile and settings. This approach not only keeps your routing clean and maintainable, but also sets the stage for introducing dynamic routing—a concept that takes flexibility and scalability to the next level.

Dynamic routes

Dynamic routing in React refers to the capability to manage routes that are not fixed but depend on varying conditions or parameters. It enables the creation of flexible paths in your application's URL structure, where segments of the URL acts as variables.

Dynamic routing is commonly used in web applications to display content or data specific to a unique identifier, such as a user ID or product ID. Rather than creating a separate route for each ID, dynamic routing allows you to create a single route to handle an infinite number of possibilities.

Implementing dynamic routing with react-router

React-router is a popular library for handling routing in React applications. It provides a set of tools that simplify the implementation of dynamic routing. To achieve this, React-router uses route parameters, which are indicated by a colon (:) followed by the name of the parameter within the path string.

When a URL matches a route pattern containing these parameters, React-router captures the values and passes them as props to the relevant component. This process enables the component to access and utilize these values dynamically.

To demonstrate dynamic routing, you will set up a simple React application with the following components:

  • App: The root component that configures the router and defines the routes.

  • ItemList: A component that displays a list of items, each with a clickable link to view more details.

  • ItemDetail: A component that shows the details of an individual item based on the dynamic URL parameter.

First, ensure you have React-router installed in your project. Next, let's explore each component and its role in dynamic routing.

App.jsx: This is the main entry point of the application. It sets up the Router and the routes for our application.

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import ItemList from './ItemList';
import ItemDetail from './ItemDetail';


const App = () => {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<ItemList />} />
        <Route path="/item/:itemId" element={<ItemDetail/> } />
      </Routes>
    </Router>
  );
};

export default App;

<Route path="/item/:itemId">: This defines a dynamic route for individual item details. The :itemId is a URL parameter that will be replaced by the actual item ID when navigating to this route.

import React from 'react';
import { Link } from 'react-router-dom';

const ItemList = () => {
  const items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' },
  ];

  return (
    <div>
      <h1>Item List</h1>
      <ul>
        {items.map((item) => (
          <li key={item.id}>
            <Link to={`/item/${item.id}`}>{item.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default ItemList;

ItemList renders a list of items using an array of objects, each with an id and a name. The .map() function is used to iterate over the array and generate a list of Link components.

List of clickable links

Each Link navigates to the dynamic route /item/:itemId when clicked, with the itemId replaced by the actual ID of the clicked item.

import React from 'react';
import { useParams } from 'react-router-dom';

const ItemDetail = () => {
  let { itemId } = useParams();

  // Here you would fetch item details from an API or data source based on the itemId
  // For demonstration purposes, we'll just display the itemId

  return (
    <div>
      <h1>Item Detail</h1>
      <p>You are viewing details for item ID: {itemId}</p>
    </div>
  );
};

export default ItemDetail;

ItemDetail.jsx: This component displays the details of the item that the user clicked on.

itemId page from dynamic routing

The component uses the useParams hook from React-router to extract the itemId parameter from the URL. The route defined in the App component (/item/:itemId) specifies that :itemId is a dynamic part of the path. When a user navigates to a URL like /item/2, React-router matches this URL with the defined route, extracts the dynamic itemId (2 in this case), and passes it to the ItemDetail component.

This is why it's called "dynamic" routing—because the route /item/:itemId can match a wide range of URLs, such as /item/1, /item/2, /item/42, and so on, with the itemId parameter taking on the value of the corresponding segment of the URL.

The main benefits of dynamic routing include:

  • Scalability: A single route definition can handle multiple paths, accommodating a wide range of IDs or parameters.

  • Flexibility: The component rendered by the route can display content that varies based on the dynamic parameters received.

  • Cleaner Code: Dynamic routing helps prevent the proliferation of similar routes, leading to a more organized and maintainable codebase.

Handling page not found

In React applications, users might navigate to routes that don't correspond to any of your components. In these instances, a "Page Not Found" or 404 error component is useful. It's crucial to provide feedback to users when they try to access a non-existent route within your application.

Implementing a 404 Error Component

To handle these situations, you can create a special component that displays a "Page Not Found" message. This component can be added at the bottom of your routing configuration to catch any undefined routes:

// App.jsx

import React from 'react';
import { BrowserRouter as Router, Routes, Route, Outlet } from 'react-router-dom';
import Home from './Home';
import DashboardLayout from './DashboardLayout';
import Profile from './Profile';
import Settings from './Settings';
import NotFound from './NotFound';

function DashboardLayout() {
  // ... (same as before)
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/dashboard" element={<DashboardLayout />}>
          <Route index element={<Profile />} />
          <Route path="settings" element={<Settings />} />
        </Route>
        {/* Catch-all route for undefined paths */}
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Router>
  );
}

export default App;

Create a new component called NotFound that will be displayed when an undefined route is accessed:

// NotFound.jsx

import React from 'react';

const NotFound = () => {
  return (
    <div>
      <h1>404 - Page Not Found</h1>
      <p>The page you are looking for doesn't exist or has been moved.</p>
    </div>
  );
};

export default NotFound;

The NotFound component is a straightfoward functional component that renders a message indicating that the page is not found. You can style this component as desired, or include links to direct users back to your application's main pages.

In the App component, we add a new Route at the bottom of our Routes that uses the path *. This wildcard path will match any URL that doesn't match the other defined routes.

When a user attempts to navigate to a route that doesn't exist, React-router will render the NotFound component, displaying the custom error message.

Error page of page not found

By placing the NotFound route last, you ensure that it only catches URLs that don't match any other routes, acting as a fallback. This is an effective way to handle 404 errors in a React application.

Conclusion

Nested and dynamic routing are essential concepts in React.js that empower developers to create complex and intuitive navigation structures within their applications. By leveraging nested routes, you can reflect the component hierarchy in your route definitions, creating a clear and organized structure. Dynamic routes enable the handling of variable patterns in your URLs, making your application adaptable to a wide range of scenarios.

By understanding and implementing these routing techniques, you can significantly enhance the user experience of your React applications, providing users with smooth and responsive navigation. As you delve further into React.js, remember the significance of routing and its capability to steer users through your application's content effectively and with ease.

8 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo