This article is a quick introduction to next.js routing where I explain the steps I took to understand it.
When you first create a NEXT.js app with
npx create-next-app
The file structure looks like this:
the pages
folder contains the page which will be rendered.
Let's add a simple page contact.js
contact.js
export default function Contact() {
return (
<div>
<h1>Contact page</h1>
</div>
)
}
open http://localhost:3000/contact
and you should see your page title
Creating a large number of pages manually becomes quickly cumbersome. Fortunately NEXT.js provides dynamic routes.
Dynamic Routes
A dynamic route is basically a javascript file under pages/
folder with special characters in its name.
basis examples
- [id].js
- [slug].js
- [user_id].js
- [name].js
catch all examples
- [...id].js
- [...slug].js
- [...user_id].js
- [...name].js
Let's create a dynamic route.
[slug].js
export default function DynamicPage() {
return (
<div>
<p>dynamic page</p>
</div>
);
}
export async function getStaticPaths() {
const posts = ["post/a", "post/b"];
const paths = posts.map((post) => ({
params: { slug: post },
}));
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
}
When you navigate to this page you get a 404
error page.
Seems legit since the folder structure
pages/[slug].js
tells next.js that the path to these pages is at the root of the site. Something like/my-page
should work. right ?
Let's navigate to /a
. And then you get this error.
Error: getStaticPaths was added without a getStaticProps in /[slug]. Without getStaticProps, getStaticPaths does nothing
Let's add a getStaticProps
[slug].js
export default function DynamicPage(props) {
return (
<div>
<p>dynamic page</p>
<p>{props.message}</p>
</div>
);
}
export async function getStaticProps(context) {
return {
props: { message: "dynamic page part 2" }, // will be passed to the page component as props
};
}
export async function getStaticPaths() {
const posts = ["post/a", "post/b"];
const paths = posts.map((post) => ({
params: { slug: post },
}));
return { paths, fallback: false };
}
The error is gone but the page is still not found.
Fix: [slug].js
You need to add the page a
in getStaticPaths
[slug].js
export async function getStaticPaths() {
const posts = ["post/a", "post/b", "a"];
const paths = posts.map((post) => ({
params: { slug: post },
}));
return { paths, fallback: false };
}
And it works
But
/post/a
is still not found.
Fix: /post/a
Remember that next.js routing is based on the folder and files structure. For /post/a
to work we need to create one of these files:
- pages/post/a.js
- pages/post/[slug].js
- pages/post/[id].js
The examples use slug
and id
but you can actually use any name since next.js use file structure to map the url path.
This file structure tells next.js to render pages if an http client requests one of the following path:
- /a
- /post/a
- /post/b
- /post/c
- /post/d
- ...
Any path starting with
/post/
becomes a valid path.
-
/post/a
path will be rendered usingpages/post/a.js
-
/post/<any>
path will be rendered usingpages/post/[slug].js
At this point, in pages/[slug].js
paths post/a
, post/b
become irrelevant. We can delete them.
Let's assume you have only two posts a
and b
You don't want to render a page for non existing posts. To achieve this, you need to add getStaticPaths
AND getStaticProps
to file pages/post/[slug].js
pages/post/[slug].js
export default function DynamicPage(props) {
return (
<div>
<p>dynamic page </p>
</div>
);
}
export async function getStaticProps(context) {
return {
props: { message: "some post" },
};
}
export async function getStaticPaths() {
const posts = ["a", "b"]; // <= the magic happens here
const paths = posts.map((post) => ({
params: { slug: post },
}));
return { paths, fallback: false };
}
This limits the valid url paths to:
/post/a
/post/b
IMPORTANT
When you use getStaticPaths
the paths params
must match the filename.
This will throw an error.
Error
Error: A required parameter (id) was not provided as a string in getStaticPaths for /post/[id]
Top comments (1)
Hey Igor, thank you for this share. I have a question, please can you help me?
I have a directory structure like this:
However, I am using i18n for the multilingual feature. And this creates a false path. For example in browser url:
This is corrupting the directory path. Should I fix this in the next.config.js file? Can you recommend any content that can be a guide?