Contenido dinámico en Next.js con el enrutador

Cómo configurar contenido dinámico en un sitio Next.js

En elPublicación anteriorvimos cómo vincular la página de inicio a la del blog.

Un blog es un gran caso de uso para Next.js, uno que continuaremos explorando en este capítulo agregandopublicaciones de blog.

Las publicaciones de blog tienen una URL dinámica. Por ejemplo, una publicación titulada "Hola mundo" podría tener la URL/blog/hello-world. Una publicación titulada "Mi segunda publicación" puede tener la URL/blog/my-second-post.

Este contenido es dinámico y puede tomarse de una base de datos, archivos de rebajas o más.

Next.js puede ofrecer contenido dinámico basado en unURL dinámica.

Creamos una URL dinámica creando una página dinámica con el[]sintaxis.

¿Cómo? Agregamos unpages/blog/[id].jsexpediente. Este archivo manejará todas las URL dinámicas bajo el/blog/ruta, como las que mencionamos anteriormente:/blog/hello-world,/blog/my-second-posty más.

En el nombre del archivo,[id]dentro de los corchetes significa que todo lo que sea dinámico se colocará dentro delidparámetro de lapropiedad de consultade Elenrutador.

Ok, son demasiadas cosas a la vez.

Cual es elenrutador?

El enrutador es una biblioteca proporcionada por Next.js.

Lo importamos denext/router:

import { useRouter } from "next/router";

y una vez que tengamosuseRouter, instanciamos el objeto del enrutador usando:

const router = useRouter();

Una vez que tenemos este objeto de enrutador, podemos extraer información de él.

En particular, podemos obtener la parte dinámica de la URL en el[id].jsarchivo accediendorouter.query.id.

Así que sigamos y apliquemos todas esas cosas en la práctica.

Crea el archivopages/blog/[id].js:

import { useRouter } from "next/router";

export default () => { const router = useRouter();

return ( <> <h1>Blog post</h1> <p>Post id: {router.query.id}</p> </> ); };

Ahora si vas alhttp://localhost:3000/blog/testrouter, debería ver esto:

Podemos usar estoidparámetro para recopilar la publicación de una lista de publicaciones. De una base de datos, por ejemplo. Para simplificar las cosas, agregaremos unposts.jsonarchivo en la carpeta raíz del proyecto:

{
  "test": {
    "title": "test post",
    "content": "Hey some post content"
  },
  "second": {
    "title": "second post",
    "content": "Hey this is the second post content"
  }
}

Ahora podemos importarlo y buscar la publicación desde elidllave:

import { useRouter } from "next/router";
import posts from "../../posts.json";

export default () => { const router = useRouter();

const post = posts[router.query.id];

return ( <> <h1>{post.title}</h1> <p>{post.content}</p> </> ); };

Recargar la página debería mostrarnos este resultado:

¡Pero no lo es! En cambio, obtenemos un error en la consola y también un error en el navegador:

¿Por qué? Porque ... durante el renderizado, cuando se inicializa el componente, los datos aún no están allí. Veremos cómo proporcionar los datos al componente con getInitialProps en la siguiente lección.

Por ahora, agregue un pocoif (!post) return <p></p>compruebe antes de devolver el JSX:

import { useRouter } from "next/router";
import posts from "../../posts.json";

export default () => { const router = useRouter();

const post = posts[router.query.id]; if (!post) return <p></p>;

return ( <> <h1>{post.title}</h1> <p>{post.content}</p> </> ); };

Ahora las cosas deberían funcionar. Inicialmente, el componente se renderiza sin la dinámicarouter.query.idinformación. Después de renderizar, Next.js activa una actualización con el valor de la consulta y la página muestra la información correcta.

Y si ves la fuente, hay ese vacío<p>etiqueta en el HTML:

Pronto solucionaremos este problema que no implementa SSR y esto perjudica tanto los tiempos de carga para nuestros usuarios como el SEO y el intercambio social, como ya discutimos.

Podemos completar el ejemplo del blog enumerando esas publicaciones enpages/blog.js:

import posts from "../posts.json";

const Blog = () => ( <div> <h1>Blog</h1>

<span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ul</span><span style="color:#f92672">&gt;</span>
  {Object.<span style="color:#a6e22e">entries</span>(<span style="color:#a6e22e">posts</span>).<span style="color:#a6e22e">map</span>((<span style="color:#a6e22e">value</span>, <span style="color:#a6e22e">index</span>) =&gt; {
    <span style="color:#66d9ef">return</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">li</span> <span style="color:#a6e22e">key</span><span style="color:#f92672">=</span>{<span style="color:#a6e22e">index</span>}<span style="color:#f92672">&gt;</span>{<span style="color:#a6e22e">value</span>[<span style="color:#ae81ff">1</span>].<span style="color:#a6e22e">title</span>}<span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/li&gt;;</span>
  })}
<span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/ul&gt;</span>

</div> );

export default Blog;

Y podemos vincularlos a las páginas de publicaciones individuales, importandoLinkdesdenext/linky usándolo dentro del bucle de publicaciones:

import Link from "next/link";
import posts from "../posts.json";

const Blog = () => ( <div> <h1>Blog</h1>

<span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ul</span><span style="color:#f92672">&gt;</span>
  {Object.<span style="color:#a6e22e">entries</span>(<span style="color:#a6e22e">posts</span>).<span style="color:#a6e22e">map</span>((<span style="color:#a6e22e">value</span>, <span style="color:#a6e22e">index</span>) =&gt; {
    <span style="color:#66d9ef">return</span> (
      <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">li</span> <span style="color:#a6e22e">key</span><span style="color:#f92672">=</span>{<span style="color:#a6e22e">index</span>}<span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Link</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">"/blog/[id]"</span> <span style="color:#a6e22e">as</span><span style="color:#f92672">=</span>{<span style="color:#e6db74">"/blog/"</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">value</span>[<span style="color:#ae81ff">0</span>]}<span style="color:#f92672">&gt;</span>
          <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">a</span><span style="color:#f92672">&gt;</span>{<span style="color:#a6e22e">value</span>[<span style="color:#ae81ff">1</span>].<span style="color:#a6e22e">title</span>}<span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/a&gt;</span>
        <span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/Link&gt;</span>
      <span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/li&gt;</span>
    );
  })}
<span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/ul&gt;</span>

</div> );

export default Blog;

Descarga mi gratisManual de Next.js


Más próximos tutoriales: