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 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/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
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!