Routing works differently in Next js compared to React js. Unlike React js, Next js routing works based on the file system concept. All the pages intended to be accessible as a route must reside in a special folder called pages.
In this tutorial, I will explain how Next js routing works with a downloadable project example. See the download option at the end of this tutorial.
Each Next js page is a React Component reside in the pages directory. Each component in the pages directory is associated with a route based on its file name. The pages directory can have sub-directories with React components in them. Each of those components gets its route based on its location directory structure.
In the above page structure, each component in the pages folder gets its route as below.
Note that any index.js components automatically become the default root for the folder. Every route will follow its domain name, for example, www.example.com/categories/realestate.
Also, note that each route has a repeated folder name and file name. That is because we are creating more files in those directories to show different dynamic route types. For static routing explained above, you can put all the category components inside the category folder without creating individual folders.
What we have discussed so far is static routing. Meaning, the router pages don't accept any variables, neither path variables nor request variables. That's not very helpful when it comes to building dynamic web applications. I will discuss five different dynamic routes in Next js.
Now, let's convert our automotive.js page to accept a path variable. All you need to do is to change the file name to [automotive].js It's a little unusual naming convention but still a valid file name. Now, /categories/automotive/[automotive].js is accisable via /categories/automotive/:variable For example, /categories/automotive/Cars and Suvs
Here is how you retrieve the variable value in the page component.
import React from 'react';
import TopMenu from '../../../components/TopMenu';
import { useRouter } from 'next/router'
function Posts({ posts }) {
const router = useRouter()
const { automotive } = router.query
return (
<>
<TopMenu />
<table>
<tr>
<th>[automotive].js Page</th>
</tr>
<tr>
<td>You are searching for: {automotive}</td>
</tr>
</table>
</>
);
}
export async function getServerSideProps({ params }) {
const users = [];
return { props: { users } }
}
export default Posts;
Alternatively, if I rename the realestate directory to [realestate], the URL variable position will replace the placeholder. /categories/[realestate]/realestate.js is accisable via /categories/:variable/realestate
For example, /categories/New York/realestate
Here is how you retrieve the variable value in the page component.
import { useRouter } from 'next/router';
import React from 'react';
import TopMenu from '../../../components/TopMenu';
function Posts({ posts }) {
const router = useRouter();
const {realestate} = router.query;
return (
<>
<TopMenu />
<table>
<tr>
<th>Realestate</th>
</tr>
<tr>
<td>
<p>This is /categories/[realestate]/realestate.js page</p>
<p>This page has /categories/***/realestate url pattern</p>
<p>You are searching realestate in <b>{realestate}</b> area</p>
</td>
</tr>
</table>
</>
);
}
export async function getServerSideProps({ params }) {
const users = [];
return { props: { users } }
}
export default Posts;
Another possibility is /categories/[realestate]/[realestate].js where [realestate].js page receives two path variables. This route is accessible via categories/New York/Two story url
Our simple dynamic route /categories/tools/[tools].js can be extended to catch all matching paths by prepending three dots to the component file name. The syntax follows as /categories/tools/[...tools].js. This route catches /categories/tools/New, /categories/tools/New/Two Story, /categories/tools/New/Two Story/Four Bedroom, etc... Note that the above route will not catch /categories/tools
import { useRouter } from 'next/router';
import React from 'react';
import TopMenu from '../../../components/TopMenu';
function Posts({ posts }) {
const router = useRouter();
const tools = router.query.tools || []
return (
<>
<TopMenu />
<table>
<tr>
<th>Tools</th>
</tr>
<tr>
<td>
<p>This is /categories/tools/[...tools].js page</p>
<p>You are searching for Tools : {tools[0]}, {tools[1]}, {tools[2]}, and are {tools[3]}</p>
</td>
</tr>
</table>
</>
);
}
export async function getServerSideProps({ params }) {
const users = [];
return { props: { users } }
}
export default Posts;
The route /categories/search/[[...search]].js catches all the routes /categories/search/[...search].js does plus /categories/search. Examples are /categories/search/cars, /categories/search/cars/4 doors, /categories/search/cars/4 doors/3500cc etc... and /categories/search
import { useRouter } from 'next/router';
import React from 'react';
import TopMenu from '../../../components/TopMenu';
function Posts({ posts }) {
const router = useRouter();
const search = router.query.search || []
return (
<>
<TopMenu />
<table>
<tr>
<th>Tools</th>
</tr>
<tr>
<td>
<p>This is /categories/search/[[]...search]].js page</p>
<p>You are searching for : {search[0]}, {search[1]}, {search[2]}</p>
</td>
</tr>
</table>
</>
);
}
export async function getServerSideProps({ params }) {
const users = [];
return { props: { users } }
}
export default Posts;
Our fully functional downloadable code project includes a deployable working example of all possible routing scenarios.
Feel free to download and deploy it for a depth understanding of how Next js dynamic routing works.
Download Next js routing example project