A Beginner's Guide to Static Routing in Next.js
Tags: nextjs, tutorial, javascript
Published: 2020-12-01 16:13:48

Routing in an application is the ability to change urls and go from one page to another. It's a major component in any web application. Thankfully, Next.js comes with a built-in logic concerning routing.

This tutorial will be focusing on static routing and cover:
* How to create routes in Next.js
    - Index Routes (such as /)
    - Static Routes (/about)
    - Nested Static Routes (/products/new_arrivals)
* How to navigate between pages and pass query parameters with:
    - Next.js Link Component
    - useRouter Hook
    - withRouter HOC

To better illustrate this concept, I will be using the example of an online store. This store will have three pages: Home, About and New Arrivals. We will be going over the different ways how to implement routing between them. Here is the end result!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gzwa0pikbheae54s1w7h.gif)

## (Optional) Starter project

There is the code for the online store: [https://github.com/mariesta/next-routing-store-project](https://github.com/mariesta/next-routing-store-project). This repository has two branches: main and final. The **main** branch has all the pages, components and styling but no routing. The **final** branch has all this + routing.

This project is a sample online store and includes three pages: Home, About Us and New Arrivals.

As a result, we will need three different URLs:
**/** for my homepage
**/about** for my about page
**/products/new_arrivals** for the page displaying the new arrivals

## How to create different routes in Next.js
Next.js uses the concept of pages to create routes. Every new Next.js project comes with a pages folder in the root directory. 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.

There are three ways to add static routes in Next.js depending on your needs.

### 1. Next.js Index Routes
Index routes are the root of a directory. By adding a index.js file to a folder, you create a new route. The pages folder itself maps to your base URL (meaning /).

Therefore, for my homepage, I will create an index.js file inside the pages folder.

**pages/index.js** would then map to */*.

### 2. Next.js Static Routes
You can also create routes by naming the file. For my about page, I want the url /about. To do so, I have created a file called `about.js` that I will put in pages.

This way, **pages/about.js** maps to **/about**.

### 3. Next.js Nested Routes
Next.js also supports nested routes. For my page with my new arrivals, I want my URL to look like /products/new_arrivals. I will create a `product` folder and then add `new_arrivals.js` inside.

**pages/products/new_arrivals.js** maps to **/products/new_arrivals**

Index routes can also be used for nested routes. Say I wanted a page for listing all my products, I would add a index.js file inside my products folder.

**pages/products/index.js** maps to **/products**

I now have all my routes mapped out and it looks like this:
```
pages/
│   index.js
│   about.js    
│
└───products/
        new_arrivals.js
```

*Note: Folder vs file? If you are wondering which to choose, ask yourself: "Will I have child routes?".*

*I am not planning to create any child routes under /about, therefore I am using a file for this page.*

*Products however could have many children routes (/products, /products/new_arrivals, /products/[id], ...). All these children routes will need separate js files. Hence, the products folder.*

Now that we have all the pages set up, it's time to implement routing between them.

## Navigate with the Next.js Link Component
The simplest way to navigate between pages is with Next.js Link Component. This component is very straightforward. Like an anchor tag, it accepts an href as a props.

Here is the Header Component for my store. I want to redirect users to the homepage when clicking on the logo. I can do so by adding a <Link> component around my anchor.
```jsx
import Link from 'next/link'

export default function Header() {
  return(
    <header className="store-header py-3">
      <div className="row flex-nowrap justify-content-between align-items-center">
        <div className="col-12 text-center">
          <Link href="/">
            <a className="store-header-logo text-dark">My Store</a>
          </Link>
        </div>
      </div>
    </header>
  )
}
```

It's the same for nested routes. Take my navbar where I have two links to the New Arrivals and the About pages. Here is the component with routing implemented.

```jsx
import Link from 'next/link'

export default function Nav() {
  return(
    <div className="nav-scroller py-1 mb-2">
      <nav className="nav d-flex">
        <Link href="/products/new_arrivals">
          <a className="p-2 text-muted">New Arrivals</a>
        </Link>
        <Link href="/about">
          <a className="p-2 text-muted">About us</a>
        </Link>
      </nav>
    </div>
  )
}
```
## Access your Next.js router and navigate with the useRouter hook
Another way to implement routing between pages is to access the router and push a new page. Next.js provides us a useRouter hook to accomplish this.

Going back to our Header Component, here is another way to link to our homepage:
```jsx
import { useRouter } from 'next/router'

export default function Header() {
  const router = useRouter()
  const navigateHome = () => router.push('/')
  
  return(
    <header className="store-header py-3">
      <div className="row flex-nowrap justify-content-between align-items-center">
        <div className="col-12 text-center">
          <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
        </div>
      </div>
    </header>
  )
}
```
With the useRouter hook, you can access the router object. The latter comes with many useful functions including push(), back(), reload() and more.

## Access your Next.js router and navigate with the HOC withRouter
The last option is, of course, with a HOC for classes. For this one, Next.js offers `withRouter` to access the router through props.
```jsx
import { withRouter } from 'next/router'

function Header({router}) {
  const navigateHome = () => router.push('/')
  
  return(
    <header className="store-header py-3">
      <div className="row flex-nowrap justify-content-between align-items-center">
        <div className="col-12 text-center">
          <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
        </div>
      </div>
    </header>
  )
}

export default withRouter(Header)
```
## Passing query parameters
The ability to pass query when navigating between pages is an important one. Next.js also covers this use case.

In these examples, I will be using my Header and Nav components to pass the query ?sort=asc to my url. This will result in urls like [http://localhost:3000/products/new_arrivals?sort=asc](http://localhost:3000/products/new_arrivals?sort=asc)

### Query Parameters with Link 
Next.js Link Component also accepts URL objects in `href`. The URL object must be composed of `pathname` (the name of the page we are trying to access) and `query` (the parameters you want to pass).
```jsx
import Link from 'next/link'

export default function Nav() {
  return(
    <div className="nav-scroller py-1 mb-2">
      <nav className="nav d-flex">
        <Link href={{
          pathname: "/products/new_arrivals",
          query: { sort: "asc" }
        }}>
          <a className="p-2 text-muted">New Arrivals</a>
        </Link>
        <Link href="/about">
          <a className="p-2 text-muted">About us</a>
        </Link>
      </nav>
    </div>
  )
}
```
### Query Parameters with useRouter
The same logic is used with the `useRouter hook`. Instead of `router.push('/')`, we replace it with `router.push({ pathname: "/", query: { sort: "asc"})`.
```jsx
import { useRouter } from 'next/router'

export default function Nav() {
  const router = useRouter();

  const navigate = (href) => router.push({
    pathname: href,
    query: { sort: "asc" },
  })

  return(
    <div className="nav-scroller py-1 mb-2">
      <nav className="nav d-flex">
        <a className="p-2 text-muted" onClick={() => navigate('/products/new_arrivals')}>New Arrivals</a>
        <a className="p-2 text-muted" onClick={() => navigate('/about')}>About us</a>
      </nav>
    </div>
  )
}
```
### Query Parameters with withRouter
And finally, with the HOC withRouter. Again, simply pass the object to `router.push()`.
```jsx
import { withRouter } from 'next/router'

function Header({router}) {
  const navigateHome = () => router.push({
    pathname: "/",
    query: { sort: "asc" },
  })
  
  return(
    <header className="store-header py-3">
      <div className="row flex-nowrap justify-content-between align-items-center">
        <div className="col-12 text-center">
          <a className="store-header-logo text-dark" onClick={navigateHome}>My Store</a>
        </div>
      </div>
    </header>
  )
}

export default withRouter(Header)
```
There you go! We have now implemented static routing in our application. And if you would like to deploy your brand new web app, what about doing it on Heroku? Here is a quick tutorial for [deploying your Next.js app to Heroku in 5 minutes](https://dev.to/mariesta/deploy-your-next-js-app-to-heroku-in-5-minutes-ldn).

If you liked the article, you can [follow me on Twitter](https://twitter.com/MStarckJS).