An Introduction To NextJS
Tags: nextjs, react, webdev
Published: 2022-02-06 07:45:42

---
published: true
title: An Introduction To NextJS
description: In this article I will give you an introduction to NextJS. What is NextJS and what problems does it solve? Learn about the React framework for production.
tags: nextjs, react, webdev
canonical_url: https://langvad.dev/blog/an-introduction-to-nextjs/
---

## What is NextJS?

NextJS is a “meta framework” for React. It provides tools and conventions that makes it easier for you as a developer. Looking at their website they write:

> *The React Framework for Production*

Lots of concepts goes in to this statement. It’s one thing to develop your application on your computer where the conditions are optimal. When taking your application live to a production environment there are many things to consider. That NextJS will help you with.

When using a classic `create-react-app` you get all the things needed from React to build a full scale application. But when putting this to production you will encounter other issues that you need to handle. Rendering is one of them. A regular React application is always rendered on the client, referred to as Client Side Rendering (CSR).

NextJS provides extra rendering options such as Server Side Rendering (SSR), Static Site Generation (SSG) and Incremental Site Regeneration (ISR). I will not go into detail about each in this article but those are the main reasons to use NextJS, I would say. Makes it easier to manage pages and components based on the rendering strategy. And you can choose which one to use depending on your specific project needs.

NextJS also provides other features such as bundling, optimised assets for production, code splitting, API routes, TypeScript support and more. All there for you as a developer to make your life easier. 

## Getting started

Open a terminal and run either this npm or yarn script.

`npx create-next-app@latest`

or

`yarn create next-app`


If you want your project to be in TypeScript you can add the `--typescript` flag after the initial command and you will have all the support and configuration files included in the boilerplate.

This will give you an application with a simple project structure.

If you open the newly created folder and run `npm run dev` or `yarn dev` you will get an app running on localhost.

## Basic concepts

NextJS provides many features out of the box. These things will make your life easier as a developer and you will create better applications.

### Pages

The most important feature is the `/pages` folder. This magic folder lets you create files that will turn into pages in your application. For example adding the file `/pages/info` will generate the path `/info`.  Try to create this page and add the following:

```jsx
export default function Info() {
  return <div>Information content</div>;
}
```

Then run your application with `npm run dev` or `yarn dev`. The new page is then accessible at `localhost:3000/info`. You can create pages by filename, but you can also create a subfolder that will map to subpaths. Another approach to the page above is to create a folder called `/info` and have a `index.js` file exporting the same code. This also opens up the option to create other files in the `/info` folder. If we were to add a new file called `contact.js` to the `/info` folder it would map to the path `/info/contact`.

This works great with static content. What if we want to fetch some data from an api and render it?

### Fetching data

NextJS provides different ways of fetching data depending on what type of application or specific page you have. The pages could be exported as static HTML pages, i.e. created at build time, or created on every request. Both ways will serve pre-rendered content and complete HTML files. Along with minimal JavaScript that is only needed to make the page interactive. You might have heard about the term `hydration`. This is the process of making a static HTML page interactive by applying the JavaScript code served alongside. This is the recommended approach to use, it has advantages on both performance and SEO. Although not being applicable in all situations.

NextJS provides 3 functions that you need to understand to be working with dynamic data.

- **getServerSideProps**
- **getStaticProps**
- **getStaticPaths**

When working with these features I always prefer to work with a real API. There are lots of free API:s to use as a developer. One of my favourites is the Star Wars API (<ins>[https://swapi.dev/](https://swapi.dev/)</ins>).

Lets create a page that will show a list of Planets from the Star Wars universe. The data for this could be fetched from the API with `https://swapi.dev/api/planets`. This will return a list of planets with lots of information about each.

Lets create a new folder called `/planets` inside our `pages` folder. Inside that folder we create an `index.js` file.

Lets add the following HTML:

```jsx
function PlanetsPage({ planets }) {
  return (
    <main>
      <h1>Planets</h1>
      {planets.map((planet) => (
        <div key={planet.name}>
          <h2>{planet.name}</h2>
          <p>Population: {planet.population}</p>
          <p>Terrain: {planet.terrain}</p>
        </div>
      ))}
    </main>
  );
}
```

This expect props to have an array of planets with name, population and terrain information. Lets get this data from the Star Wars API. For this we use the `getServerSideProps` function. To get this to work you only have to export a function called `getServerSideProps` from the page file. Put this above or below the `PlanetsPage` function.

```jsx
export async function getServerSideProps() {
  const res = await fetch('https://swapi.dev/api/planets');
  const data = await res.json();

  return { props: { planets: data.results } };
}
```

Here two things are happening:

1. Data is being fetched from the example API
2. An object with a `props` property is returned from the function

What we return as `props` will be available as `props` in the `PlanetsPage` function. This is magically handled by NextJS. 

Now when navigating to `localhost:3000/planets` you should see a list of planets. 

When using `getServerSideProps` the HTML document will be created on every request. The example data we are working with is very static and is perfect to be statically generated. For this we can use the `getStaticProps` function. It works the same as `getServerSideProps` and the only thing we need to do is to replace the function name.

```jsx
export async function getStaticProps() {
  const res = await fetch('https://swapi.dev/api/planets');
  const data = await res.json();

  return { props: { planets: data.results } };
}
```

This should work exactly the same as before. The difference is this will create the HTML pages at build time. You can try this out and see for yourself. If you run `npm run build` with `getStaticProps` you can see the generated HTML page at `.next/server/pages/planets.html`. Changing the method to `getServerSideProps`, deleting the `.next` folder and run `npm run build` again. The same HTML file will not be created. Being able to decide what methods to use means you can use statically generated pages on some pages and server side rendered on others. This is a really powerful feature.

**Dynamic data**

It’s often common to have dynamic paths depending on the content being fetched. A blog post might have a specific slug for example. In this example we want to add a page for a specific planet. We can fetch a planet by adding an id to the path (`https://swapi.dev/api/planets/1`). In our application we then want to add a path for `/planets/1`. To achieve this we will create a new page under the planets folder and use the function `getStaticPaths`. This needs to be in combination with `getStaticProps` to work.

Create a file called `/planets/[id].js`. The square bracket notion means a dynamic path.

First add the HTML part that only requires the data for one planet this time.

```jsx
function PlanetPage({ planet }) {
  return (
    <main>
      <h1>{planet.name}</h1>
      <p>Population: {planet.population}</p>
      <p>Terrain: {planet.terrain}</p>
    </main>
  );
}
```

Then we add the `getStaticProps` to get the data for one specific planet. Getting the id from the url. `getStaticProps` receives a context object from which we can get the params for the current path.

```jsx
export async function getStaticProps(context) {
  const res = await fetch(`https://swapi.dev/api/planets/${context.params.id}`);
  const data = await res.json();

  return { props: { planet: data } };
}
```

Then add the `getStaticPaths` function to generate the pages based on the content:

```jsx
export async function getStaticPaths() {
  const res = await fetch('https://swapi.dev/api/planets');
  const data = await res.json();

  const paths = data.results.map((planet, i) => ({
    params: {
      id: i.toString(),
    },
  }));

  return {
    paths,
    fallback: true,
  };
}
```

Here we are fetching all the planets and create an paths list. 

`getStaticPaths` must return an object with a paths array. The array should contain objects that must have a property mapping to the name of the dynamic page. In this case `id`. The value of id must be a string. For a blog post this could be named `slug` and the filename be `[slug].js` etc.

*Note: in this case the Star Wars API does not return the id for each entry. Normally you would want to create your pages based on some value for each entry. As the specific planet is fetched by an increasing id we can in this case use the index within the map function. This is not recommended in a real application.*

If you run `npm run build` or `yarn build` you will get an output with all the pages created. For me it looks something like this:

```bash
├ ● /planets (429 ms)
└ ● /planets/[id] (3171 ms)
    ├ /planets/8 (444 ms)
    ├ /planets/5 (436 ms)
    ├ /planets/4 (412 ms)
    ├ /planets/6 (366 ms)
    ├ /planets/1 (327 ms)
    ├ /planets/2 (323 ms)
    ├ /planets/3 (319 ms)
    └ [+3 more paths]
```

If you start up your application again you can now navigate to `/planets/1` and you should see the content for only that planet.

The complete file for the PlanetsPage then looks like this. You can place the exported functions either before or after the page function. I prefer to have them before.

```jsx
export async function getStaticProps(context) {
  const res = await fetch(`https://swapi.dev/api/planets/${context.params.id}`);
  const data = await res.json();

  return { props: { planet: data } };
}

export async function getStaticPaths() {
  const res = await fetch('https://swapi.dev/api/planets');
  const data = await res.json();

  const paths = data.results.map((planet, i) => ({
    params: {
      id: i.toString(),
    },
  }));

  return {
    paths,
    fallback: false,
  };
}

function PlanetPage({ planet }) {
  return (
    <main>
      <h1>{planet.name}</h1>
      <p>Population: {planet.population}</p>
      <p>Terrain: {planet.terrain}</p>
    </main>
  );
}

export default PlanetPage;
```

## Going forward

This was just a quick introduction to NextJS. We have learned about the concepts of pages and filename routing. How we could fetch data depending on specific situations. I will continue to add more posts about all the other specific features in the future. 

To continue working on your application and explore all the other features of NextJS I recommend to start reading their documentation <ins>[https://nextjs.org/docs/getting-started](https://nextjs.org/docs/getting-started)</ins>.