We can create server-side rendered React apps and static sites easily Next.js.
In this article, we’ll take a look at routing with Next.js.
Dynamic Route Links
We can add links for dynamic routes.
To do this, we write:
pages/foo.js
import Links from './links';
function Foo() {
return <div>
<Links />
<p>foo</p>
</div>
}
export default Foo
pages/blog/[slug].js
import { useRouter } from 'next/router'
import Links from '../links';
const Post = () => {
const router = useRouter()
const { slug } = router.query
return <div>
<Links />
<p>Post: {slug}</p>
</div>
}
export default Post
pages/links.js
import Link from 'next/link'
const posts = [
{ slug: 'hello-world', title: 'hello world', id: 1 },
{ slug: 'good-news', title: 'good news', id: 2 },
{ slug: 'great-news', title: 'great news', id: 3 },
]
function Links() {
return (
<ul>
<li>
<Link href="/foo">
<a>foo</a>
</Link>
</li>
{posts.map((post) => (
<li key={post.id}>
<Link href="/blog/[slug]" as={`/blog/${post.slug}`}>
<a>{post.title}</a>
</Link>
</li>
))}
</ul>
)
}
export default Links
We have the [slug].js
file which displays the slug that we pass in.
router.query
has the URL parameters in an object.
It can have as many URL parameters as we pass in.
The useRouter
hook has the route data.
We need the brackets to indicate that the file is used for dynamic routes that can accept URL parameters.
The links.js
file has the links.
We use the Link
component for adding the links.
The href
has the URL pattern for the route.
And as
has the actual path for the route to fo to.
Also, we have a static link to the foo
page.
Therefore, when we click the links, we’ll go to the pages that are mapped to the routes.
We should see the slug when we click on the last 3 links.
Catch All Routes
We can add catch-all routes by adding ...
before the file name.
For example, we can write:
pages/blog/[...slug].js:
import { useRouter } from 'next/router'
import Links from '../links';
const Post = () => {
const router = useRouter()
const { slug } = router.query
return <div>
<Links />
<p>Post: {slug.join(', ')}</p>
</div>
}
export default Post
pages/links.js
import Link from 'next/link'
const posts = [
{ slug: 'hello-world/1', title: 'hello world', id: 1 },
{ slug: 'good-news/2', title: 'good news', id: 2 },
{ slug: 'great-news/3', title: 'great news', id: 3 },
]
function Links() {
return (
<ul>
<li>
<Link href="/foo">
<a>foo</a>
</Link>
</li>
{posts.map((post) => (
<li key={post.id}>
<Link href="/blog/[slug]" as={`/blog/${post.slug}`}>
<a>{post.title}</a>
</Link>
</li>
))}
</ul>
)
}
export default Links
We added an extra URL parameter to each slug
.
They’re rendered as arrays in [...slug].js
.
Therefore, we called join
to convert the array into a comma-separated string.
Optional Catch-all Routes
We can make catch-all routes optional by adding extra brackets around the file name.
For example, we can write:
pages/blog/[[...slug]].js
import { useRouter } from 'next/router'
import Links from '../links';
const Post = () => {
const router = useRouter()
const { slug } = router.query
return <div>
<Links />
<p>Post: {slug && slug.join(', ')}</p>
</div>
}
export default Post
We wrapped an extra set of brackets around the file name.
Now we can go to the /blog
path and we’ll see the same page without anything after Post:
.
Conclusion
We can add dynamic route links with Next.js.
All we have to do is to follow the file name convention and use the href
and as
props with the Link
component.