Introduction
Dynamic routing in Next.js allows you to create pages with dynamic paths based on data, making your application more flexible and powerful. This guide explores how to set up dynamic routing in Next.js, including dynamic routes, nested routes, and catch-all routes.
1. Dynamic Routing
Dynamic routing enables the creation of pages that depend on the data provided at runtime. Instead of hardcoding paths, you define routes using dynamic segments, which Next.js maps to specific pages dynamically.
2. Setting Up Dynamic Routes
Creating Dynamic Routes
To create dynamic routes, use square brackets [param] in your file names. For example, to create a route for individual blog posts, you can create a file named [id].js inside the pages/posts directory.
Example
Create the File Structure
pages/
posts/
[id].js
Add Dynamic Route Logic
// pages/posts/[id].js
import { useRouter } from 'next/router';
const Post = () => {
const router = useRouter();
const { id } = router.query; // Access the dynamic parameter
return (
<div>
<h1>Post {id}</h1>
{/* Fetch and display post content based on `id` */}
</div>
);
};
export default Post;
Fetching Data for Dynamic Routes
To fetch data for dynamic routes, use getStaticProps and getStaticPaths for Static Site Generation (SSG) or getServerSideProps for Server-Side Rendering (SSR).
Example with getStaticProps and getStaticPaths
Generate Static Paths
// pages/posts/[id].js
export async function getStaticPaths() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json();
// Generate paths based on data
const paths = posts.map(post => ({
params: { id: post.id.toString() },
}));
return { paths, fallback: 'blocking' }; // Use 'blocking' or 'true' for fallback
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
const post = await res.json();
return {
props: { post },
};
}
const Post = ({ post }) => (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
export default Post;
3. Nested Dynamic Routes
For nested dynamic routes, create nested folder structures.
Example
File Structure for Nested Routes
pages/
posts/
[id]/
index.js
comments.js
Fetching Data for Nested Routes
// pages/posts/[id]/comments.js
import { useRouter } from 'next/router';
const Comments = ({ comments }) => {
const router = useRouter();
const { id } = router.query;
return (
<div>
<h1>Comments for Post {id}</h1>
<ul>
{comments.map(comment => (
<li key={comment.id}>{comment.body}</li>
))}
</ul>
</div>
);
};
export async function getServerSideProps({ params }) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}/comments`);
const comments = await res.json();
return {
props: { comments },
};
}
export default Comments;
4. Catch-All Routes
Catch-all routes handle multiple dynamic segments. Use [...params] to catch all paths.
Example
Create a Catch-All Route
// pages/posts/[...slug].js
import { useRouter } from 'next/router';
const Post = () => {
const router = useRouter();
const { slug } = router.query; // slug is an array of parameters
return (
<div>
<h1>Post {slug.join('/')}</h1>
{/* Fetch and display post content based on `slug` */}
</div>
);
};
export default Post;
5. Dynamic Routes with API Routes
Dynamic API routes can be set up similarly using [param] in the pages/api directory.
Example
Create API Route
// pages/api/posts/[id].js
export default async function handler(req, res) {
const { id } = req.query;
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
const post = await response.json();
res.status(200).json(post);
}
6. Best Practices for Dynamic Routing
- Use getStaticPaths for static generation: Use getStaticPaths to pre-render pages with dynamic segments.
- Leverage fallback options: Choose appropriate fallback behavior (false, true, or 'blocking') based on your needs.
- Validate data: Ensure you validate and handle errors for dynamic routes and API responses.
Summary
Dynamic routing in Next.js offers powerful ways to create flexible and scalable applications. By using dynamic, nested, and catch-all routes, you can build complex routing structures that adapt to your data. Employ these techniques to enhance your Next.js applications and provide a robust user experience.