Dynamic Routing and Catch-All Routes in Next.js

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/2or/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 likepush,replace, andback.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/appdirectory.
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/pagesdirectory.
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
Blogs:
/blog/[slug]for articles with unique slugs.
E-Commerce:
/products/[id]for individual product pages.
Documentation:
/docs/[...slug]for structured documentation paths.
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!






