Checkout my CSS Grid By Example and Getting Started With React video courses on Skillshare. Sign up now and get one free month of Skillshare.

Example of using the generateStaticParams() in NextJs 13 within the app folder

See how to use the generateStaticParams() function with the app folder to build predefined static paths.

Let's say we want to build an app to display information about some pokemon characters like the one in the image below:
preview for the app build with generateStaticParams() in NextJs 13

The folder structure is using dynamic segments to send URL params for the name of the displayed character :

/app
    /pokemon
        /[name]
            page.js

Even if they are dynamic, we want to have paths like the ones below ready at build time:

/pokemon/bulbasaur
/pokemon/ivysaur
/pokemon/venusaur
// ...

First step will be to use the fetch function to get all the pokemon characters from the API. This will be done on the layout page:

// app/layout.js
import Link from "next/link";
import { getPokemons } from "./getPokemons";

export default async function Layout({ children }) {
  const { results } = await getPokemons();

  return (
    <div style={{display: 'flex', gap: '2rem'}}>
      <ul>
        {results.map(({ name }, i) => (
          <li key={`${name}_${i}`}>
            <Link href={`/pokemon/${name}`}>{name}</Link>
          </li>
        ))}
      </ul>
      {children}
    </div>
  );
}

Given that the getPokemons() function is needed both in the main layout of the app and also in the individual character page we will have this function placed in its own file so that we can import it in both places:

// app/getPokemons.js
export async function getPokemons() {
  const res = await fetch("https://pokeapi.co/api/v2/pokemon");
  return res.json();
}

Finally, in the app/pokemon/[name]/page.js we will use the generateStaticParams() function to define the list of segments that will be generated at build time instead of on-demand at request time:

import Image from "next/image";
import { getPokemons } from "../../getPokemons";

async function getPokemon( name ) {
  const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
  return res.json();
}

export default async function Page({ params }) {
  const { name, sprites } = await getPokemon(params.name);
  const img = sprites.other.home.front_default;

  return (
    <div>
      <h1>{name}</h1>
      <Image
        alt={`Artwork for ${name}`} 
        src={img} width={200} height={200}  />
    </div>
  );
}

export async function generateStaticParams() {
  const pokes = await getPokemons();
  return pokes.results.map((p) => ({ name: p.name }));
}

This will ensure that all characters returned from the getPokemons() request have a pre-build page with all the needed data fetched upfront.

You can checkout the full code here.

Some notes on the generateStaticParams() function:

  • in older versions of NextJs the replacement for this function was getStaticPaths()
  • be sure to match the name of the dynamic segment with what you are returning from the function or you will get the required parameter was not provided as a string in generateStaticParams error
  • if you want to highlight the active navigation link in NextJs I've written a tutorial about this
  • if you have a catch-all segments path, and want to send multiple params you can return an array from the function:
    //app/store/[...data]/page.js
    export async function generateStaticParams() {
    return [
        { data: ['electronics', '1'] }, // -> /store/electronics/1,
        { data: ['clothing', '2'] },  // -> /store/clothing/2,
        { data: ['books', '3'] }  // -> /store/books/3
        // ...
    ];
    }
Home Screencasts Best of Newsletter Search X