Next JS routing what you need to know

Routing in Next JS is quite different from what we are used to with React Router. Initially, it is quite easy to start but later it becomes tricky. I have started using Next JS recently and in the beginning, it was a mess because Next JS is using React as a library and they put their convention on top of it. SSR is another reason for the new conventions.

You might use to with the React router where you are adding Route component and mentioning which component to mount. Just like below.

React Router routing example

In Next JS it is quite different. They pulled kinda old school way to set up the route. You might remember we created about.php, home.php when started learning web development or maybe the extension is something else other than php. Next JS routing is working a similar way. There is a folder in Next JS installation called pages. If you create a file there (about.jsx, contact.jsx) it would be accessible via browser respectively /about and /contact. Quite easy right?

But this is not enough, we need more feature like getting query param from URL (/about?name=”John Doe”) and also nested route (/about/asifsaho).

The _app file

You might have seen there is a file called _app.jsx or _app.tsx in the pages folder which is actually wrapping your root level component (Ex: about.jsx or about.tsx) automatically. Usually, this file contains all providers, for example, Apollo Provider, Auth provider and so on. Those providers are providing common data to other components mounting inside this _app file. The _app file looks like below.

Collecting Query params

This component also provides router prop where you will find all of your query params. Have a look at destructuring statement just before the return. you can add a new item there like below.

const { apollo, Component, pageProps, router } = this.props;

Now you can pass this to child components so that you can access it. Your return statement might look like below.

      <Container>
        <Auth0Provider
          domain={process.env.AUTH0_DOMAIN}
          client_id={process.env.AUTH0_CLIENT_ID}
          redirect_uri={redirectURI}
          audience={process.env.API_AUTH0_AUDIENCE}
          scope=""
          onRedirectCallback={onRedirectCallback}>
          <ApolloProvider client={apollo}>
            <Layout>
              <Component {...pageProps} router={router} />
            </Layout>
          </ApolloProvider>
        </Auth0Provider>
      </Container>

How the nested Route works in Next JS

Now the tricky part Nested route. Before releasing Next 9 it was not so peaceful because it was required to create a server for this. Recently Next 9 made it a bit easier but unfortunately, it is not conventional. I have never seen this style before. It is a whole new way of routing. The good thing is it is quite easy to learn.

Let’s assume we have a route called /about and we need another nested route under about which might look like /about/asifsaho. Now we need to create a page for the nested route and get the asifsaho (:username) to the page. I prefer to create a folder about and put index.tsx or index.jsx in that folder which will match /about like before (same as about.tsx without the folder). Now we need to put the nested route page which will match /about/:username. Let’s put a file called [username].tsx or [username].jsx under the about folder.

This structure will not match and work perfectly if you refer to /about/:username from a Link component. We need to explicitly say that it should use the [username] file.

<Link href={'/about/[username]'} as="/invoices/asifsaho">
    <a>Profile</a>
</Link>

Now you can make the implementation dynamic like below

<Link href={'/about/[username]'} as={`/invoices/${username}`}>
    <a>Profile</a>
</Link>

Now the question is how to get this username inside the [username] page/component. We need to use useRouter method from next/router package to get the username. The basic example of the component is below. If you are not using TypeScript please remove the types.

import { useRouter } from 'next/router';
import React from 'react';

const InvoiceDetail: React.FC = () => {
  const router = useRouter();
  return <div>{router && router.query && JSON.stringify(router.query)}</div>;
};

export default InvoiceDetail;

Multi-level nested Route

Now the question is how to match the multi-level route with more than one variable. Maybe you need something like below

/blog/:blogId/comments/:commentId.js

In this scenario, you need to create a few more folders. Your folder and file structure should be like this.

./pages/blog/[blogId]/comments/[commentId].js

It sounds a bit oldish, right? but this is how Next JS is. As they introduced the file-based routing this is the solution they are offering.

Cool, it is done. ✅ Thank you for reading the tutorial. Hope it will help you guys. Let me know what you are thinking. I will try adding more information later. Good luck dealing with Next JS.