Skip to main content

Command Palette

Search for a command to run...

Dynamic Routing and Catch-All Routes in Next.js

Updated
4 min read
Dynamic Routing and Catch-All Routes in Next.js
S

Full-stack developer with a passion for building scalable web applications using Next.js, TypeScript, and modern technologies. Experienced in ServiceNow development and scripting. Sharing knowledge and insights on web development and programming.

Dynamic routing in Next.js allows you to create flexible routes that adapt to user input. This feature is particularly useful for building dynamic applications like blogs, e-commerce sites, and user-specific dashboards. Additionally, Next.js provides robust support for handling non-existent routes through custom 404 pages and catch-all routes.


What is Dynamic Routing?

Dynamic routing enables you to define routes where part of the URL can change dynamically. For example:

  • /product/[id] can match URLs like /product/1, /product/2 or /product/special-item.

Difference Between next/navigation and next/router

Both next/navigation and next/router offer routing utilities, but they cater to different environments within Next.js.

next/navigation

  • Scope: Specifically designed for the App Router (introduced in Next.js 13).

  • Features:

    • useParams: Access dynamic route parameters.

    • useSearchParams: Access query parameters.

    • useRouter: Provides navigation methods like push, replace, and back.

    • notFound: Programmatically trigger 404 pages.

    • redirect: Redirect users to a specific URL.

Recommended Use: When using the App Router for building routes in the src/app directory.

next/router

  • Scope: Designed for the Pages Router (traditional routing system in Next.js).

  • Features:

    • useRouter: Access the router object for navigation and dynamic route handling.

    • query: Access route parameters and query strings.

    • prefetch: Prefetch pages for better performance.

  • Recommended Use: When building applications in the src/pages directory.


Creating Dynamic Routes

Step 1: Define a Dynamic Route File

To create a dynamic route, use square brackets ([ ]) in your file or folder name within the pages or app directory. For example:

src/app/products/[id]/page.tsx

Step 2: Access the Dynamic Parameter

Inside your dynamic route, you can access the parameter using params (in the App Router) or query (in the Pages Router).

App Router Example:

interface ProductPageProps {
  params: { id: string };
}

export default function ProductPage({ params }: ProductPageProps) {
  return <h1>Product ID: {params.id}</h1>;
}

Pages Router Example:

import { useRouter } from 'next/router';

export default function ProductPage() {
  const router = useRouter();
  const { id } = router.query;

  return <h1>Product ID: {id}</h1>;
}

Inside your dynamic route, you can access the parameter using the params object provided by Next.js.

Example Using App Router:

import { notFound } from 'next/navigation';

interface ProductPageProps {
  params: { id: string };
}

export default function ProductPage({ params }: ProductPageProps) {
  if (!params.id) {
    notFound();
  }

  return <h1>Product ID: {params.id}</h1>;
}

Alternatively, use the useParams hook from next/navigation:

import { useParams } from 'next/navigation';

export default function ProductPage() {
  const params = useParams();

  if (!params.id) {
    return <h1>404 - Product Not Found</h1>;
  }

  return <h1>Product ID: {params.id}</h1>;
}

Catch-All Routes

Catch-all routes match multiple URL segments and are defined using [...param] in the file or folder name.

Example:

src/app/docs/[...slug]/page.tsx

Handling Catch-All Parameters:

interface DocsPageProps {
  params: { slug: string[] };
}

export default function DocsPage({ params }: DocsPageProps) {
  const slugPath = params.slug.join('/');

  return <h1>Viewing: {slugPath}</h1>;
}

This route will match paths like:

  • /docs

  • /docs/getting-started

  • /docs/tutorials/advanced


Optional Catch-All Routes

You can make a catch-all route optional by adding a question mark (?) in the file name:

This matches both /docs and any nested paths under /docs.

By adding a question mark (?) after the ...slug part, you can make the catch-all segment optional, meaning the route will match even if there's no additional path segment after the base URL.

pages/docs/[...slug]?
This route will match:
- /docs
- /docs/post-title
- /docs/category/article-name
  • Usage:

    This is particularly useful for creating fallback pages or handling situations where a user might access a URL with or without additional parameters.


Handling 404 Errors

Next.js allows you to create a custom 404 page for non-existent routes.

Step 1: Create a 404 Page

In the App Router:

src/app/not-found.tsx

In the Pages Router:

src/pages/404.tsx

Step 2: Define the Custom 404 Page

export default function NotFound() {
  return <h1>404 - Page Not Found</h1>;
}

With the App Router, you can also use the notFound() function to programmatically trigger a 404:

import { notFound } from 'next/navigation';

export default function ProductPage({ params }: { params: { id: string } }) {
  if (!params.id) {
    notFound();
  }

  return <h1>Product ID: {params.id}</h1>;
}

Practical Use Cases

  1. Blogs:

    • /blog/[slug] for articles with unique slugs.
  2. E-Commerce:

    • /products/[id] for individual product pages.
  3. Documentation:

    • /docs/[...slug] for structured documentation paths.
  4. Custom 404 Pages:

    • Enhance user experience with branded 404 pages.

Conclusion

Dynamic and catch-all routes in Next.js provide a flexible and powerful way to build dynamic applications. By understanding how to create and use these routes effectively, you can handle a wide variety of use cases, from user-specific pages to structured documentation paths. Start exploring dynamic routing today to unlock the full potential of your Next.js applications!

More from this blog

S

Strnge Blogs

27 posts

Welcome to my Hashnode blog! I'm a passionate technologist with a background in web dev. Through my blog, I aim to share insights and thoughts on various tech topics that intrigue me.