We will start by creating a NextJs app using the creat-next-app command. I will be using npx to create a new project called my-pokemon-app. For this tutorial, we will be making use of the Pokemon API(https://pokeapi.co/) to demonstrate how to consume external APIs using NextJs.

npx create-next-app@latest my-pokemon-app

Let’s navigate to our project and open the code in the editor of our choice.

cd my-pokemon-app

You can notice, the create-next-app creates a bunch of folders and files necessary for us to run a NextJs project.

nextjs folder structure

To check if everything is set up without any issues, we will run the next server using the npm run dev command in the terminal. This should start the application on port 3000 by default http://localhost:3000/.

nextjs default home page

The above content is displayed using the pages/index.js file. For the purpose of this tutorial, we will be using this file to display some of the Pokemon characters using the Pokemon API. Let’s clean up this file and delete any code that we don’t require.

You can simply copy the below code into your pages/index.js file.

import Head from "next/head";
import styles from "../styles/Home.module.css";

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Pokemon App</title>
        <meta name="description" content="Fetch api data using NextJs" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Pokemon App using Next.js!</h1>
      </main>
    </div>
  );
}

The page should now look something like this:

nextjs api pokemon

Now that we have set up our NextJs app, we can now work on getting the data from the Pokemon API. NextJs provides three different functions to fetch data into our app. They are getStaticProps, getServerSideProps and getStaticPaths. We will first look at the getStaticProps method.

Fetching data using the getStaticProps

The getStaticProps function is used when you want to pre-render the content at the build time. This function gets executed on the server side and pre-fetches all the content even before the user request’s the data.

We will pre-fetch some of the Pokemon characters using the getStaticProps function and display it on our index page.

Let’s add the getStaticProps function below the Home() function (you can also add it at the top, it does not matter).

import Head from "next/head";
import styles from "../styles/Home.module.css";

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Pokemon App</title>
        <meta name="description" content="Fetch api data using NextJs" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Pokemon App using Next.js!</h1>
      </main>
    </div>
  );
}

export async function getStaticProps() {

  return {
    props: {

    }
  }
}

The getStaticProps returns props that contain the data fetched from the external API. We can use this data to display on the client side.

We will use the fetch to call the pokemon API and store the result in pokemons which can be used to pass as props to the client side.

export async function getStaticProps() {
  const res = await fetch("https://pokeapi.co/api/v2/pokemon");
  const pokemons = await res.json();

  return {
    props: {
      pokemons
    },
  };
}

The props pokemons can now be used in the Home() function to display the content.

export default function Home({ pokemons }) {
  const { results } = pokemons;
  return (
    <div className={styles.container}>
      <Head>
        <title>Pokemon App</title>
        <meta name="description" content="Fetch api data using NextJs" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Pokemon App using Next.js!</h1>
        
        {results.map((result) => (
          <div className={styles.grid} key={result.name}>
            <a href="/" className={styles.card}>
              <h2>{result.name} &rarr;</h2>
            </a>
          </div>
        ))}
      </main>
    </div>
  );
}

The API response contains a results array which contains the name of the 20 pokemons by default. We have destructured the results array and looped through them using the map() method. If everything goes well your app should now display the names of pokemons from the API.

nextjs list pokemon api external

Fetching data using the getServerSideProps

The getServerSideProps function uses a server-side rendering technique. If NextJs finds a getServerSideProps function declared within a page, it will pre-render the page every time the request is made to that page with the data returned by getServerSideProps. This function always runs on the server side.

To demonstrate getServerSideProps function, we will create a dynamic page route which will list the details of individual Pokemon. In this case, we will fetch the data using getServerSideProps.

We will start by creating a new folder within the pages folder and name it pokemon. Within the pokemon folder we will create another folder [id] which will help us with the dynamic routing. Lastly, we will create a file index.js inside the [id] folder that will call the getServerSideProps function.

nextjs nested routing

Let’s create a new function pokemon in the newly created index.js file.

export default function pokemon() {
  return (
    <>
      <h1>Pokemon</h1>
    </>
  );
}

This should help us access the route like ‘/pokemon/xxx’

nextjs pokemon

Next, we will update the link on the home page to point to the dynamic routes. We will use the name of the pokemon as the id. Open the /pages/index.js and replace the href value to point to the dynamic route.

{results.map((result) => (
    <div className={styles.grid} key={result.name}>
      <a href={"pokemon/" + result.name} className={styles.card}>
        <h2>{result.name} &rarr;</h2>
      </a>
    </div>
  ))}

Let’s go ahead and add the getServerSideProps function in the pokemon/[id]/index.js

export default function pokemon() {
  return (
    <>
      <h1>Pokemon</h1>
    </>
  );
}

export async function getServerSideProps(context) {
  return {
    props: {},
  };
}

The getServerSideProps takes a context parameter which is an object containing keys like params, req, res, query etc. Since we are using dynamic routing, we will make use of the params key to get the ‘id’.

Let’s call the URL to fetch the individual data as follows:

export async function getServerSideProps(context) {
  const id = context.params.id;
  const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
  const pokemon = await res.json();
  return {
    props: { pokemon },
  };
}

We can now use the pokemon props to display the content.

import styles from "../../../styles/Home.module.css";

export default function pokemon({ pokemon }) {
  return (
    <>
      <main className={styles.main}>
        <h1>Pokemon - {pokemon.name}</h1>

        <div className={styles.card}>
          <img
            src={pokemon.sprites.other["official-artwork"].front_default}
            alt={pokemon.name}
            width="200"
            height="200"
          />
          <p>Height: {pokemon.height}</p>
          <p>Weight: {pokemon.weight}</p>
        </div>
      </main>
    </>
  );
}

nextjs pokemon getserversideprops 1

nextjs pokemon getserversideprops 2

nextjs pokemon getserversideprops 3

code: https://github.com/kushald/my-pokemon-app