Dynamic Routing and Route Segments (Parallel & Catch-All Routes)

Table of Contents

  1. Introduction
  2. What is Dynamic Routing in Next.js?
  3. Defining Dynamic Routes
  4. Route Segments and Nested Routes
  5. Parallel Routes
  6. Catch-All Routes
  7. Handling Multiple Dynamic Parameters
  8. Dynamic Route Matching: Examples
  9. Best Practices for Dynamic Routing
  10. Conclusion

1. Introduction

In modern web development, dynamic routing allows for more flexible and scalable applications. Next.js, with its App Router and file-based routing system, offers a robust and intuitive way to handle dynamic routes and segments.

This module will explore dynamic routing in Next.js, with a focus on route segments, parallel routes, and catch-all routes. You’ll learn how to create routes that respond to user input or data, organize nested routes, and utilize advanced routing techniques for handling multiple dynamic parameters.


2. What is Dynamic Routing in Next.js?

Dynamic routing refers to the ability to create routes that change based on parameters in the URL. In Next.js, dynamic routing is enabled by using brackets in the file names, allowing you to define paths that change according to input, such as /products/[id] or /users/[username].

The App Router in Next.js allows for both static and dynamic route generation. When you use dynamic routing, Next.js can automatically map routes to specific data or content based on URL parameters, reducing the need for manually managing route configurations.


3. Defining Dynamic Routes

In Next.js, dynamic routes are defined by placing square brackets around a file or folder name. These brackets represent dynamic segments that will match any value for that portion of the URL.

Example: Basic Dynamic Route

Let’s define a dynamic route for displaying user profiles:

tsxCopyEdit// app/users/[id]/page.tsx
export default function UserProfile({ params }) {
  return <div>User ID: {params.id}</div>;
}

In this case:

  • The route /users/[id] will match any path like /users/123 or /users/abc.
  • The params.id will provide access to the dynamic portion of the URL, such as 123 or abc.

You can also define optional parameters by appending a question mark (?) to the bracket, allowing for routes like /users/[id?], where the id can be omitted.


4. Route Segments and Nested Routes

Route segments refer to parts of the URL that correspond to nested file or folder structures in the Next.js application. This hierarchical structure allows for the creation of nested routes, enabling complex URL patterns that map to different components or pages.

Example: Nested Routes

tsxCopyEdit// app/products/[category]/[id]/page.tsx
export default function ProductDetail({ params }) {
  return (
    <div>
      <h1>Product ID: {params.id}</h1>
      <p>Category: {params.category}</p>
    </div>
  );
}

In this example:

  • The route /products/[category]/[id] matches paths like /products/electronics/123.
  • The route is dynamic, so it can handle any category and product ID.

This approach works seamlessly with nested layouts in Next.js, where each layout component can handle a specific segment of the URL.


5. Parallel Routes

Parallel Routes allow for rendering multiple different views on a single route simultaneously, based on different layout segments. This is useful when you want to display multiple components independently in different sections of a page.

Example: Parallel Routes

In the example below, the layout has two parallel routes—one for the main content and another for the sidebar:

tsxCopyEdit// app/dashboard/layout.tsx
import { ParallelRoute } from 'next';

export default function DashboardLayout({ children }) {
  return (
    <div style={{ display: 'flex' }}>
      <div style={{ flex: 3 }}>{children.main}</div>
      <div style={{ flex: 1 }}>
        <ParallelRoute name="sidebar" />
      </div>
    </div>
  );
}

In this example:

  • The children.main renders the primary content.
  • The ParallelRoute name="sidebar" renders the sidebar component in parallel.

This feature is particularly useful for building dashboards, admin panels, or any page with sections that should independently fetch data or render without affecting other areas of the page.


6. Catch-All Routes

A Catch-All Route allows you to handle any route that matches a certain pattern. It’s like a wildcard that can match multiple segments in the URL, even if you don’t know the exact number of segments in advance.

Example: Catch-All Route

tsxCopyEdit// app/blog/[...slug]/page.tsx
export default function BlogPost({ params }) {
  return <div>Blog Post: {params.slug.join('/')}</div>;
}

In this example:

  • The route /blog/[...slug] will match paths like /blog/2023/nextjs-tips or /blog/2023/nextjs-tips/seo.
  • The params.slug array captures all parts of the route after /blog/, so you can handle multi-segment routes in a single component.

Catch-all routes are particularly useful when you need to support flexible content paths or multi-level nested URLs.


7. Handling Multiple Dynamic Parameters

You can also handle routes with multiple dynamic parameters by nesting dynamic route segments inside other dynamic segments. This allows for complex URLs and gives you full flexibility in routing.

Example: Multiple Dynamic Parameters

tsxCopyEdit// app/[category]/[subCategory]/[productId]/page.tsx
export default function ProductDetail({ params }) {
  return (
    <div>
      <h1>Category: {params.category}</h1>
      <h2>Subcategory: {params.subCategory}</h2>
      <p>Product ID: {params.productId}</p>
    </div>
  );
}

In this example:

  • The route /products/[category]/[subCategory]/[productId] dynamically handles three segments.
  • The params object will contain category, subCategory, and productId, allowing you to display the correct content based on the URL.

8. Dynamic Route Matching: Examples

Let’s explore a few common use cases for dynamic routes in a real-world app.

Example: User Profile with Dynamic Username

tsxCopyEdit// app/users/[username]/page.tsx
export default function UserProfile({ params }) {
  return <div>Profile of {params.username}</div>;
}

If a user navigates to /users/johndoe, the params.username would contain "johndoe", and the component would render the profile for John Doe.

Example: Filtering Content Based on Dynamic Parameters

tsxCopyEdit// app/products/[category]/page.tsx
export default function CategoryPage({ params }) {
  return <div>Showing products in category: {params.category}</div>;
}

If a user navigates to /products/electronics, it would show products under the “electronics” category.


9. Best Practices for Dynamic Routing

  • Use Descriptive and Simple Routes: Make sure dynamic routes are intuitive. Use meaningful parameters to improve the URL structure, such as /products/[category]/[id] instead of complex or overly nested routes.
  • Handle Optional Parameters: Use optional parameters when you need flexibility, such as a profile page that may or may not include a user ID.
  • Avoid Too Many Nested Routes: While nested routes are powerful, excessive nesting can make it harder to manage your codebase. Consider flattening the structure when possible.
  • Leverage Catch-All Routes: Use catch-all routes sparingly and only when you need to support variable URL structures, as they can make debugging more complex.

10. Conclusion

Dynamic routing is one of the core features that makes Next.js a flexible and powerful framework for building modern web applications. With the ability to use dynamic route segments, parallel routes, and catch-all routes, you can create complex, responsive, and SEO-friendly pages that scale efficiently.

Understanding how to utilize these advanced routing techniques is key to building high-performance, maintainable web applications. Whether you are building a blog, an e-commerce site, or a dashboard, Next.js provides the tools you need to handle dynamic routing seamlessly.

By mastering dynamic routing and route segments, you can improve the user experience by delivering content that is directly relevant to each user’s needs and behavior.