Next.js has one of the most robust and easy to use routes that you can just use out of the box. You don't need to hassle by configuring it.
Because Next.js follows the Convention over Configuration
philosophy, every file inside the pages
directory will be autmatically considered as a route.
So, let's see what different types of routing we get with Next.
Static Routing
Let's create an About
page for our blog app
For it, just create a file about.js
insided pages
directory
touch pages/about.js
with content
export default function About() {
return(
<div>About</div>
)
}
That's it. Next's built HMR should automatically pick up the added file, and create a route for it.
Just go to localhost:3000/about
and you should see your about page.
Now, let's think for some reason you need to structure your about
routes in a different
maybe
localhost:3000/about -> Opens the about us
localhost:3000/about/contact -> Opens the contact page
localhost:3000/about/some_random_page -> Opens some random page you need to show
For that, you need your folder structered like this
> pages
> about
index.js
contact.js
some_random_page.js
Let's create them
mkdir about
mv pages/about.js pages/about/index.js
We renamed our old about.js
file to index.js
and moved it inside the pages/about
folder.
If you refresh the page, it'll behave in the same way.
touch pages/about/contact.js
export default function Contact() {
return(
<div>Contact Us</div>
)
}
and your weird random page
touch pages/about/some_random_page.js
export default function SomeRandomPage() {
return(
<div>bla bla bla</div>
)
}
Dynamic Routing
Ofcourse, you can just use Static routes
for some simple urls.
Let's think you're creating a blog and you need to show your posts through posts/1
url
The folder structure for that will be
> pages
> posts
index.js
[id].js
the index.js
file is for your all posts
page.
What about the weird [id].js
file?
This is a special syntax used by Next.js called slugs. The string inside the [
and ]
brackets denote which param the page will receive.
Let's see the code
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { id } = router.query
return <p>Post: {id}</p>
}
export default Post
We need to import the useRouter
module from next/router
to catch which param was sent in the URL.
That is done by the following code
const router = useRouter()
const { id } = router.query // < { id } because we named the slug in filename as [id].js
if you instead named your slug as [post_id].js
, then the code should be
const router = useRouter()
const { post_id } = router.query
Now, if you visit the url posts/1234567
the page will receive the data { "id": "1234567" }
and render
Catch all routes
So, what about when you want to pass more data through the url and catch them in the following page.
in that case, we will need Catch all routes
. It's syntax is like
> pages
> posts
index.js
[...slug.js]
This will match posts/1
, at the same time match posts/1/2/3/abc
and so on.
Remember with [id].js
we received the vlaue like { "id": "1234567" }
With [...slug.js] we will receive the value in an array.
So, posts/a/b
will give you { "slug": ["a", "b"] }
import { useRouter } from 'next/router'
const Article = () => {
const router = useRouter()
const slug = router.query
console.log(slug);
return <p>Article</p>
}
export default Article
If you go to localhost:3000/articles/12/32
it'll get an array [12, 32]
That's it.
Shallow Routing
Shallow routing is used for changing the url without fetching any data.
This means getStaticProps
or getServerSideProps
will not be called.
Example:
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// Current URL is '/'
function Page() {
const router = useRouter()
useEffect(() => {
// Always do navigations after the first render
router.push('/?counter=123', undefined, { shallow: true })
}, [])
useEffect(() => {
// The counter changed!
}, [router.query.counter])
}
export default Page
The URL will get updated to /?counter=123
and the page won't get replaced, only the state of the route is changed.