Generando estáticamente rutas dinámicas en Next.js con 'getStaticPaths' y 'getStaticProps'

Supongamos que necesitas desarrollar un blog, sin duda alguna, una de las tareas a resolver será generar las rutas por cada entrada de blog. Para ello, recuerda que Next.js permite generar rutas dinámicas, para este ejemplo, tendrías una estructura similar a la siguiente:

├── pages
│   └── blog
│       ├── [id].js
│       └── index.js

es decir, para la entrada de blog con id: 1 podrás acceder de la siguiente forma: blog/1.

Ahora bien, considerando que tus posts están alojados en una API, tal vez te cuestiones ¿Cómo puedo generar estáticamente todas las entras de blog?. Venga, yo se que tú puedes, para ello, Next.js cuenta una función llamada getStaticPaths, la cual, nos permite especificar las rutas que deseemos pre-renderizar. Suena bastante bien, no crees?.

Dentro de dicha función, necesitarás obtener todos los posts con los que cuentas, para poder así, generar las rutas que desees pre-renderizar.

Para fines demostrativos, utilizaré el API Rest de jsonplaceholder, que cuenta con información básica de 100 posts.

Veamos como quedaría:

/* blog/[id].js */

export async function getStaticPaths() {
  
  // Obteniendo todos los posts desde un API Rest
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts = await response.json()
  
  // Extrayendo las rutas que se pre-renderizarán (basado en la cantidad de posts)
  // Pasando el id de cada post (se utilizará más adelante)
  const paths = posts.map((post) => ({
    params: {
      id: post.id.toString(),
    }
  }));

  return {
    paths, // Se pre-renderizarán estas rutas en el momento de construcción
    fallback: false // Cualquier [id] no válido generará un error 404
  }
}

Con está función, Next.js generará estáticamente blog/1, blog/2, ..., blog/100 en el momento de construcción, utilizando el componente de pages / blog / [id].js.

Sólo un paso más...

Además de la función getStaticPaths que hemos visto previamente, necesitarás utilizar la función getStaticProps, que se encargará de recuperar los datos sobre cada post, para poder así, usarlos y pre-renderizar la página correctamente, recuerda que getStaticProps también es llamada en tiempo de construcción.

/* blog/[id].js */

export async function getStaticPaths() {
  // ...
}

export async function getStaticProps({ params }) {

  // Obteniendo un post basado en su id
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
  const post = await response.json();

  // Pasando los datos de el post a la página vía props.
  return {
    props: {
      post,
    }
  }
}

Listo!, con estás dos funciones has generado estáticamente rutas dinámicas, ahora ya tendrás la información necesaria para poder presentar tu componente:

/* blog/[id].js */
export async function getStaticPaths() {
  // ...
}

export async function getStaticProps({ params }) {
  // ...
}

const BlogPost = ({ post }) => {
  return (
    <section>
      <h1>{post?.title}</h1>
    </section>
  )
}

El momento ha llegado!, ve a tu navegador y dirígete a alguna de las rutas disponibles, por ejemplo: blog/17, el título del post deberá mostrarse en pantalla. Si intentas acceder a una ruta que no esta definida: /blog/101, el resultado será un 404.

Espero te haya sido útil este post, si tienes alguna duda, comentario ó sugerencia de está implementación, no dudes en dejar tu comentario aquí abajo. 👇