Learn Next.js setting up & routing in no time

What is Next.js?

Next.js is a production-ready React Framework. What does this really mean? if you are familiar with React, you know that you can not use React alone for production-ready applications. You need to add other supporting libraries as your web application or web design project requires.

React is a library that is responsible for the user interface( view).

On the other Next.js is built to create full-stack web applications. It provides the functionality needed to develop and make your application ready for production and deployment. 

How to start a Next.js project

First, you need to install Node.js 10.13 or later. Then, open the terminal and run the following command.

npx create-next-app my-next-app

This will prompt you to install the “create-next-app” package. Say “y” for that, and this will install all the dependencies needed to build a web application in Next.js.

After successful completion of the installation process, open the project folder in your favorite editor. 

You should see the following project structure. 

Now, let us see what is on package.json

There are a few scripts we need to understand in this file.

dev: This will start the development server if you execute npm run dev.

build: running this will compile the Next.js app and make it ready for production and  deployment

When you run this script, you will note a new folder named .next is generated. The Next.js app servers are from this folder. You will also note that this folder is in the .gitignore file.

Start: this will run the built application in production mode.

Lint: lints all the files in the application, which is analyzing your code to find any issues with it.

Important folders in the Project structure

There are some important folders in this strict project structure (Thus, Next.js is opinionated unlike Reactjs).

public: This folder holds all the public resources. The content of this folder can be accessed directly in the root domain. At the moment, do not worry about what this means. We are going to discuss this more later so that you will understand it clearly. 

pages: this folder contains the source code of the application that is responsible for routing, layout, and rendering in the browser. There are 2 files one folder created by default.

API folder: holds API routes. Next.js create one API route by default(hello.js)

_app.js: defines the layout of the application. This file will render both in client and server.

The flow of control in Next.js

When you run npm run dev(or yarn dev), your application starts in the development mode. The control of execution moves to _app.js. _app.js has a React functional component with two props: Component & pageProps. 

Component prop refers to the active page renders in the browser. In the default settings, the Component prop receives the Home component in the index.js file.

pageProps is an object which contains if there are any initial props of the rendered page. Otherwise, pageProps is an empty object. In the default settings, this object is empty. You can test this. Remove the pageProps prop from the functional component ( MyApp) in the _app.js, and you will still be able to render the Home component. 

Public folder

Now, let’s discuss the public folder.

First, run the default application created in the development mode with npm run dev/ yarn dev. By default, it should serve on localhost:3000.

You can access the contents of the public folder, including content in subfolders, as it is the root domain. These contents can be a text file, HTML file, image file, etc.

Create a text file or an HTML file, or add an Image file and you can access those files as it is in the root domain. Do your experiment by creating a subfolder as well.

http://localhost:3000/myimage.png

http://localhost:3000/sample.txt

http://locahost:3000/samplefolder/sample.html

You can notice that Next.js matches files with the routes. A concept that seems to borrow from traditional PHP web applications. We will talk about routing in Next.js next.

How does Routing work in Next.js?

Routing in Nex.js is based on the file system. This means when you add a file to the pages folder in your Next.js project, that file is automatically mapped to a new route. 

  1. Add a new file named sample.js in the pages folder.
  2. Add the following code
import React from 'react'
export default function sample() {
  return (
    <div>This is the sample page</div>
  )
}

Now, in the browser, you can access this page in the following route

http://localhost:3000/sample

There are different types of routes available in Next.js for your needs. 

  • Index routes
  • Nested routes
  • Dynamic routes
  • Catch-all routes
  • Navigation with LINK component
  • Navigate programmatically between pages

Index routes

In Next.js, any index.js is mapped to the root of the directory structure (‘/’). 

Ex:

pages/index.js   ⇒ http://localhost:3000/

pages/mydocs/index.js  ⇒ http://localhost:3000/mydocs   ( here, mydocs is a folder)

Nested routes

Next.js can match nested folders in the pages folder as it is with the route.

pages/mydocs/alldocs.js ⇒ http://localhost:3000/mydocs/alldocs

pages/mydocs/blog/firstpost.js ⇒  http://localhost:3000/mydocs/blog/firstpost

  1. Create another folder named blog in the mydocs folder
  2. Add a file in the blog folder: firstpost.js
  3. Add the following code to firstpost.js and save it.
import React from 'react'
 
export default function sampepost() {
  return (
    <div>This my first post</div>
  )
}

You can access this page on the following route in the browser

http://localhost:3000/mydocs/blog/firstpost

Although you can do many levels of nesting folders and map them with the route, it is best to keep nested routes maximum to 4 or 5 levels in depth.

Dynamic routes

With index routing and nested routing, you know exactly the page and the path to it. But, what if you do not know what route the user would take at a certain point on your web application. This is where you need dynamic routes. Let’s see a typical use case.

  1. Create a folder inside the pages folder. Name it “book”.
  2. Inside the “book” folder, create two files:
    1. Index.js
    2. And the [name].js
      • That is right. It should be inside square brackets. When you add brackets to a page in Next.js, it creates a dynamic route.
import React from 'react'
export default function BookIndex() {
  return (
    <div>
        <h2>My Favorite Books</h2> 
        <li><a href="book/book1">Book 1</a></li>
        <li><a href="book/book2">Book 2</a></li>
        <li><a href="book/book3">Book 3</a></li>
    </div>
  )
}

[name].js

import { useRouter } from 'next/router'
 
export default function Book(){
  const router = useRouter();//access the router object
  const { book } = router.query;
 
  return (
            <div>
                <h3>Information on { book }</h3>
                     <p>name: { book }</p>
                     <p>author: john</p>
        </div>
  );
 
}

Learn more on router object

If a user clicks on book1 ( at http://localhost:3000/book/)  Router. query returns { “book”: “book1” }.

routerouter.query
book/book1{ “name”: “book1” }
book/book2{ “name”: “book2” }
book/book3{ “name”: “book3” }

Some other examples

1/book/book1?chapter=chapter1 {chapter: ‘chapter1’, book: ‘book1’}
2/book/book1?name=book4{book: ‘book1’}

In the second example above route parameters override the query string parameters ( name=book4 ) because Your route parameter is [name] and your query parameter is also “name“.

Nested Dynamic routes

You can also create nested dynamic routes.

Note: If you have [ name ].js in your book folder at this stage, please delete it. Otherwise, you will get the error:

 “Failed to reload dynamic routes: Error: You cannot use different slug names for the same dynamic path”

After you delete [ name].js from the book folder, do the steps below.

  1. Create a folder inside the book folder you created before, and name it as [fiction].
  2. Now, create another folder inside the [fiction] folder. Name it as [review]
  3. In the [review] folder, create a file: [reviewId].js

Add the following code to [reviewId].js

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

export default function Review() {
    const router = useRouter();
    const { fiction , reviewId } = router.query;
  return (
    <div>
        <label>name:</label><p>{ fiction }</p><br />
        <label>review ID:</label><p>{ reviewId }</p>
    </div>
  )
}

Now you can try the following URL in the browser. I use beloved ( name of a novel ) and 3 as the dynamic value. 

http://localhost:3000/book/beloved/review/3

book/[fiction]  is mapped to   ../book/beloved

../../[review]/[reviewId].js  is  mapped to   ../../review/3

Catch all routes

A catch-all route is a way to catch all possible dynamic routes. Let us see with a new example

  1. Create a new folder in the pages folder; name it “customer”.
  2. Inside the “customer” folder, create a file. Name it as […param].js. You can give any name you want, param is only a convention. 
  3. The directory structure pages/customer/[…params].js can now match any dynamic route

http://localhost:3000/customer/review

http://localhost:3000/customer/item/100/review/5

http://localhost:3000/customer/review/100/time/item

The matched parameters in the URL are stored in an array as a query parameter in the router object.

Therefore, you can use the length of this array and elements in your code in […param].js to achieve any desired outcome you need for a particular dynamic route. 

In […params].js add the code below

import React from 'react'
import { useRouter } from 'next/router';
 
export default function Customer() {
    const router = useRouter();
    //set params to an empty array to avoid run time error
    const { params = []} = router.query;
    let view = '';
 
    if( params.length == 0 ){
        view = "No customers"
    }
    else if( params.length === 3 ){
            view = <h1>customer  name :{ params[0]} <br /> { params[1] } :   { params[2] }</h1>
    }else if( params.length === 1 ) {
            view = <h1>customer name: { params[0]}</h1>
    }
 
  return (
    <div>
       { view  }
    </div>
  )
}

After you add the code, you can try the following URL examples in the browser

http://localhost:3000/customer/john

http://localhost:3000/customer/john/rating/5 

Now, enter the following URL in the browser

http://localhost:3000/customer

Did you see a 404-page loading in your browser?

This is because the params array is undefined because of pre-rendering in Next.js. To avoid this 404 at the base of a catch-all route, you can modify the […params] as follows

[[…params]]

Now, if you look at the router object, you can see the query object is empty.

The router will automatically route files named index to the root of the directory.

Navigation with next/link component

The link component provides smooth transitions between pages since, unlike the anchor tag, it does not reload the whole HTML page.

Let us see an example.

Create a new folder in the pages folder, and name it “product”.

In the “product” folder create 3 files

index.js

import React from 'react'
import Link from 'next/link'
 
export default function Home() {
  return (
    <div>
        <h1>Home page</h1>
        <li><Link href='product/laptop'>
            <a>Laptop</a>
        </Link>
        </li>
        <li>
        <Link href='product/desktop'>
            <a>Desktop</a>
        </Link>
        </li>
    </div>
  )
}

laptop.js

import React from 'react'
 
export default function laptop() {
  return (
    <h1>laptop product page</h1>
  )
}

desktop.js

import React from 'react'
 
export default function desktop() {
  return (
    <h1>desktop product page</h1>
  )
}

Navigating programmatically with router methods

You can make use of methods in the router object whenever a link component does not provide sufficient functionality for your application. You can often use these methods in functions that execute on user events such as clicking a button.

Create a new file named order.js in the product folder you created in the above example. Add the following code.

order.js

import React from 'react'
 
export default function order() {
  return (
    <div>placing order .....</div>
  )
}

Now change the code in the desktop.js as follows.

import React from 'react'
import { useRouter } from 'next/router'
 
export default function desktop() {
    const router = useRouter();
 
    const handleClick = () => {
        router.push('./order')
    }
 
  return (
        <div>
        <h1>desktop product page</h1>
        <button onClick={ handleClick }>place an order</button>
    </div>
  )
}

Now when you go to the desktop page and click on the button you should go to the URL below

http://localhost:3000/product/order

You can learn more about the next/router and its methods here.

Summary

In this post, I show you how to set up Next.js, the React framework on your computer. Then, we discuss various ways Next.js provides for routing. We learned index routes, nested routes, dynamic routes, Catch-all routes, navigation with LINK component, and navigating programmatically.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top