Skip to content

Instantly share code, notes, and snippets.

@amandeepmittal
Created December 6, 2018 13:28
Show Gist options
  • Save amandeepmittal/f860a01fa04c87807bdbc33fa62c0742 to your computer and use it in GitHub Desktop.
Save amandeepmittal/f860a01fa04c87807bdbc33fa62c0742 to your computer and use it in GitHub Desktop.

How To Build a React App with Next.js

Introduction

Working with a modern JavaScript using a React as the front-end framework comes with its own problems. You want to focus on building and releasing/shipping the application for the user rather than spending too much time configuring and managing code-splitting, determining the content loading architecture, and bundling them together in order to serve it as a web application.

Welcome, Next.js. It is a promising React framework that targets above-mentioned problems and is often advertised as a zero-configuration framework for React applications. Often, when you are releasing a public app or a website, you need to render the content for search engines to optimize your website. Next.js tend to solve this problem too by handling server-side rendering for you.

In this tutorial, we are going to build a small React app using the Next.js framework. On completing this tutorial you will have experience with setting up and building an app with Next.js but also realize how much it is handling for you out of the box.

Pre-requisites

To continue with this tutorial, you will need the following:

  • npm installed on your machine.
  • Knowledge of ES6 JavaScript features such anonymous arrow functions =>, import and export statements, async/await and so on.
  • React itself

First Universal JavaScript App

A Next.js project can be easily initialized using npm. Create a new directory and traverse inside it, and install the following dependencies.

https://gist.github.com/dbd7e1f184d205dabd9162cb7e403339

Next step is to edit the package.json file with following scripts.

https://gist.github.com/f666b82fb0b57bad31907a425507c5cb

If you run the command npm run dev now, there will be an error stating that there is a missing pages folder. There is a significance to the name of this folder which we will discuss later. For right now, to get started, create a new folder pages in the root of your project and inside create a new file called index.js with the following content.

https://gist.github.com/683ff7ab4c53a245e979c37ab7fb1480

The file-system of your project is the main API that Next uses to serve on the client. Every .js file becomes a route and gets rendered. Now run the npm run dev command from your terminal and go to URL http://localhost:3000/ to see the following result.

(ss1)

Note that you can define your own port as a command line option when running the dev script. npm run dev -- -p <your port here>. 3000 is the default port used by Next when there is no custom port number defined.

Now, in a typical React project, you might be having webpack to bundle your component files, or in our case pages/index.js and use Babel to transpile the JavaScript/JSX code inside it. Next does this automatically for you. Another important aspect to notice here is that Next uses Hot Code Reloading when in development mode. Any changes you make inside index.js file are going to be automatically reflected in the browser window.

(ss2)

Creating Pages

The pages directory here is the routing system Next uses. There is no need for react-router or any other routing library integration. Now let us add another page. Create a new file called second.js with the following content.

https://gist.github.com/4179e573b6156a2bbdbc5f6fc288f125

This page can be simply accessed using the URL http://localhost:3000/second. You can even have sub-directories and use them as a normal route. For example, create a new sub-directory inside pages/crypto/index.js with a file and the following code.

https://gist.github.com/352c24b322ed81d5adcadf7fd4f41241

To see this in action, you can visit the URL http://localhost:3000/crypto and see the following message in the browser window.

(ss3)

Another thing to notice here is that we are not using the import React... statement in crypto/index.js file. You can use anything from React in Next without having to import it. Next has its own presets when compiling the code and adds that for you. If you want to see how it does that, you will notice that in your project there is a hidden directory called .next. Visit this path: .next/static/development/pages/crypto to view how Next is rendering our routes behind the scene. You will also notice it uses Webpack.

Routing in Next.js

Now we have three pages in the Next.js project. In this section, let us learn how to do proper client-side navigation in Next.js that is SEO friendly. In order to support client-side navigation, let us use Next.js' Link API, which is exported via next/link.

Edit both index.js and second.js files like below in order to make this recipe work.

https://gist.github.com/34a01c5bc5d0498092e7472f5734b483

In the above code snippet, do notice that the href attribute is used on Link rather than <a> tag. This Next.js way of doing things. Also, using anchor tag inside <Link> makes it SEO friendly.

https://gist.github.com/7f9b8dd2a023db2be182111d1468f8d8

You can verify the results below.

(ss4)

Building a Real Time App

So far we have covered the basics of Next.js. Not all concepts, there is more to it, but I have left some for this section. This section onwards, you are going to build a real-time application using Next.js and apply the routing knowledge you have just learned. You are going to build a Hacker News clone using their API and along the way, an important concept of using APIs in a Next.js application. So let us get started.

Initializing the Project

You can start a new project and follow the same procedure of initializing it with npm and installing the required dependencies. Once you have done that, create the pages/ directory and add a home page in a file called index.js. Run the npm run dev command and see if everything is working fine.

https://gist.github.com/d24e1c84474bf7780a48f758d3a9a344

Now, let us install a dependency that is going to make AJAX requests to the Hacker News API to fetch stories and help us display them through our own custom React components. Install the following package from your terminal.

https://gist.github.com/80d88cad50e01120dd2e2712443abadb

Why are we using this package instead of the fetch API that comes with latest JavaScript or even a more popular module like axios that is common in React community? The fetch API is a just a polyfill for browsers which do not have it available as a function yet. The fetch API adds the function itself to the window object of your browser. The package you are going to use isomorphic-fetch is an implementation of fetch for both the server (Node.js part) and the browser build up on that polyfill.

Fetching Data from the API

Now, let us fetch those stories from the API. For our demo purpose, I am going to use an open-source API called node-HNAPI. Edit the index.js file by importing fetch from isomorphic-fetch, creating a class component from React.Components and initializing the props in order to fetch the stories.

https://gist.github.com/60b762dc26bd2d155a4cc3316ba09b01

To load data on when the home page of the application loads, in Next.js we use, getInitialProps which is an async method. This means, it can fetch the data required asynchronously and resolves the result or response object in the case above into a plain JavaScript object that populates React's props. Data returned from getInitialProps is serialized when server rendering, similar to a JSON.stringify.

One thing to remember here is that, in any Next app, you can only use getInitialProps in a file that exists inside the pages/ directory. It cannot be used with children components.

Using try/catch block, we are fetching stories from the API URL https://node-hnapi.herokuapp.com/news?page=1. The significance of using try/catch will become clear to you later as we are going to deliberately cause an error in the app and hook a way to handle it. Lastly, the render function gets stories from this.props and using JavaScript's map we can query on the array which currently holds the data to display it on the screen. Try running the npm run dev command and see the following result like below.

(ss5)

Using built-in Error Page

Next.js provide you a built-in error page to display to the user in a case when there is a problem fetching the data from the API. This is available through Error Component from next/error and can be used directly in the code. Modify the index.js file like below.

https://gist.github.com/50479854debe4ed3192d68b0ecdb1a36

In the above snippet, the API link is not correct. It will not fetch the data and instead show a weird error that is recommended not to be shown on the client side because the end user doesn't care about the specific error. That is for us to handle. Changing the previously working API URL to error-causing non-functional URL: https://node-hnapi.herokuapp.com/abs, is handled in the render function using the built-in Error component as shown above. Do take a note that, we are passing an empty array to stories in the catch block to check if the stories are unavailable due to some reason, we can display the following to the end user.

(ss6)

After this step, leave out built-in error part but change the API URL back to https://node-hnapi.herokuapp.com/news?page=1 and things will start working again.

Using Component in Next.js

Using re-usable components in Next.js is completely identical to how you would do the process in any React application. This certainly clarifies the beginner doubts related to Next.js is all about pages. Let us build one for ourselves.

Create a new directory in the root of the project and name it components. Inside it, create a new component StoryList.js with the following code.

https://gist.github.com/ff07f4496a70484d7adb04999fdbd20e

This component receives all stories from the page index.js as props. To make this work, you will have to import this component inside index.js and pass stories that are being fetched from the API as props.

https://gist.github.com/49adeb590b2676563aa48c3da41c6510

Let us now continue to build the component in order to display other details we are getting them from the API. If you visit the API URL https://node-hnapi.herokuapp.com/news?page=1 you will notice that each story is an object that contains different information including points, comment counts and the link to the individual story to its original URL. We start by importing the Link from next/link.

(ss7)

We are going to leverage that object. Modify StoryList component like below.

https://gist.github.com/7e048de1e1406ce68cf972db57476560

The title is another link that will re-direct you to the link of the original post but does not use Next's Link component.

(ss8)

Styling Components in Next.js

Our Hacker News Clone does so far what we are telling it to do. However, the look and feel are unappealing. In this section, you are going to make it look decent. Next.js comes pre-loaded with a CSS framework called styled-jsx to design your React components. It allows you to write scoped CSS rules inside your component using the familiar CSS syntax.

Normally, in a React app, you can use style={{}} directly to add styling. In Next.js, you do not use style directly. Instead, you use <style jsx></style> element and all styles are written inside a template string.

Open StoryList.js to add the following styling.

https://gist.github.com/f6725a1672b43897743596dee4f5baac

Visiting the home page URL in the browser window, you will get a similar look.

(ss9)

This looks okay but if we are making a simple clone, putting a bit more effort can result in similar results. Create a new component called Layout.js inside components/. This will be like the navigation menu bar on the original Hacker News site.

https://gist.github.com/f86d8ca715de55b491fa03f652324ce6

From the above code, you can note that is a simple component that has its own styling with one navigation item, the title. Do notice how we are defining the global styles using <style global jsx>. These styles are going to be applied to any children component of this component. This component also accepts children components. In our case, that is going to be the StoryList component. Open the pages/index.js file, import the Layout component and change the render method.

https://gist.github.com/9e611af5031331ee8d90c4996d576d1d

(ss10)

Head Component In Next.js

Right now, if you take a look at the browser window, in the title section of the tab, you won't see anything other than localhost....

(ss11)

This certainly notifies us that we are missing a head element which is used to set the title of any page on any website or application dynamically. Next has a custom Head component that can be imported from next/head. From our index.js we are going to send the title of the app as props.

https://gist.github.com/b2a901bdf47aa5743a861b94fdac035d

To receive these props, open Layout.js and add the following.

https://gist.github.com/25da0c0609a27bf585c1eb2f39fc3f34

Head component can be used for SEO purposes like by adding a description. I am not going to go into SEO details here as it will be out of the context of this article.

Pagination

In this section, you are going to implement a dynamic way to fetch stories from Hacker News API endpoint that are listed on page two, three and so on. Currently, on the home page, the stories that are being displayed are only from the first page of the Hacker News API. If you remember the URL 'https://node-hnapi.herokuapp.com/news?page=1' you can see, we have hardcoded the query parameters page=1.

The getInitialProps in Next provides a context of the server that further contains details about the req and the res, where both are HTTP objects for request and response. Another parameter we can pass in it is called query which is generally defined as the string section of URL parsed as an object.

Now, we are going to define a custom variable called page inside the getInitialProps. By default, its value is going to be 1 which indicates that initially, it will be loading the first page. To fetch the next page, it will get increment by 1 every time the user clicks a button. Then we pass this page variable as props to the Index class.

https://gist.github.com/31cfe0fa5bead8e43870a345b03e694e

By using Link component, we are defining a button that uses a dynamic approach to trigger and loads the next page from the API. Take a look at the href={`/?page=\${page + 1}`}. You will now find a Load More button which triggers this behavior into the action.

(ss12)

Similarly, just by adding another button you can decrement the number of pages to visit the previous page.

https://gist.github.com/c54806b68ac02acf3f88c68eeefb3f56

(ss13)

Conclusion

This completes our tutorial. The prospect of extending this application or the demo we built as a clone are many. Some of the features you can try extending are displaying comments for each individual story as the next page in this application. Next.js tries to solve the problem as a framework by increasing development speed, taking of care of tooling, and bundling the application behind the scenes. Rest if your effort with a mixture of imagination and curiosity of what you can build using it.

The complete code of this tutorial can be found in the Github repository below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment