This week, the topic of this tutorial is dynamic routing in Next.js. More precisely, we will go over:
- How to create dynamic routes
- How to navigate between pages with the Link component
- How to retrieve the query parameters (like ids)
How to create dynamic routes in Next.js
As mentioned in the tutorial on static routing, Next.js defines routes based on the concept of pages
.
What does that mean? Every Next.js project comes with a pages folder. The structure of the pages folder determines the structure of your routes and every file inside that folder maps to a route in your application.
Essentially, every time you want to create a route, you need to add a file in the pages folder. Keep in mind that the pages folder itself represents your root url (meaning /).
For static routing, you can create a new route by adding a index.js or a named file like about.js.
pages/index.js maps to /
pages/about.js maps to /about
Tip: For more info on how to create static routes (including nested routes), read my tutorial on static routing in Next.js.
But how does it work for dynamic routes? Say I wanted to create a blog, how would I add a route such as myblog.com/posts/:id?
Next.js handles dynamic routes by supporting brackets around parameters (e.g [id]) as a filename. Going back to my blog example, I would therefore create a [id].js file inside my posts folder.
As a result, /pages/posts/[id].js would map to /posts/[id] where id is the unique id of your post.
Dynamic Nested Routes in Next.js
Can I create dynamic nested routes? Say I wanted a page for comments related to a particular post, could I have a url such as /posts/[id]/[commentId]?
The answer is Yes!
For nested routes, you have to create a folder instead of a file. The syntax stays the same meaning that your folder would be called [id]. You can then add new routes inside. Here is the end result:
pages/
│ index.js -> url: /
│
└───posts/
| index.js -> url: /posts
|
└─── [id]/
index.js -> url: /posts/[id]
commentId.js -> url: /posts/[id]/[commentId]
Now that all our routes are set up, let's explore how to navigate between the different pages.
How to navigate to dynamic routes in Next.js
Next.js offers a component called Link that allows for navigation between pages. This component accepts an href and wraps around a piece of code (say an anchor) to navigate to a page. Let's try it.
Try #1:
import Link from "next/link";
export default function Home() {
return (
<div>
<h1>Welcome to my blog</h1>
<div>
<Link href="/posts/1">
<a>Post #1</a>
</Link>
</div>
</div>
);
}
Straightforward, but hard-coded links are not very practical. I am going to create a separate posts object and use that to create my url.
Try #2:
import Link from "next/link";
const posts = [
{
id: 1,
title: "Post #1"
},
{
id: 2,
title: "Post #2"
}
];
export default function Home() {
return (
<div>
<h1>Welcome to my blog</h1>
{posts.map((post) => (
<div key={`post-${post.id}`}>
<Link href={`/posts/${encodeURIComponent(post.id)}`}>
<a>{post.title}</a>
</Link>
</div>
))}
</div>
);
}
Better! But what if I update my route later? I will have to go through all my code and update all the links.
Try #3:
import Link from "next/link";
const ROUTE_POST_ID = "posts/[id]";
const posts = [
{
id: 1,
title: "Post #1"
},
{
id: 2,
title: "Post #2"
}
];
export default function Home() {
return (
<div>
<h1>Welcome to my blog</h1>
{posts.map((post) => (
<div key={`post-${post.id}`}>
<Link
href={{
pathname: ROUTE_POST_ID,
query: { id: post.id }
}}
>
<a>{post.title}</a>
</Link>
</div>
))}
</div>
);
}
What changed? Instead of an hard-coded url, the Link component can also accept an object for href.
This object contains two parameters pathname and query. The pathname is the route we want to navigate to (in our particular case, /posts/[id]) and the query which will contain all the data necessary for our dynamic route (like id).
The Link component takes those two and automatically formats it into the right url. That's much better!
Access query parameters in your page
Can I access the parameters in my new page? In other words, when I get to /posts/[id], can I get the id part?
You can get all the information you need and more from the router itself. Simply, import useRouter and get the router object. The same way, we pass a query object for navigating query : { id: post.id }
, we can retrieve it in our new page.
import { useRouter } from "next/router";
export default function PostPage() {
const router = useRouter();
return <div>Post #{router.query.id}</div>;
}
There you go! I created a sandbox if you would like to see the complete code and play around with it a bit: Next.js Dynamic Routing CodeSandbox.
If you liked the article, you can follow me on Twitter.
Top comments (0)