No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
3 Hrs
35 Min
5 Seg

Moviendo al servidor: getStaticPaths

11/19
Recursos

¿Cómo se utiliza Get Static Props en Next.js?

Cuando construimos aplicaciones web, una estrategia eficiente de renderizado puede marcar la diferencia en la experiencia del usuario. En Next.js, getStaticProps juega un papel crucial para optimizar nuestras páginas, especialmente cuando se trata del "Build Time". Este método es ideal para las páginas no dinámicas ya que proporciona a React información de manera anticipada sobre qué datos se requerirán.

¿Cómo funciona getStaticProps?

  • Solo se ejecuta una vez, durante el proceso de construcción (build time).
  • Determina los datos necesarios para mostrar la página estáticamente.
  • Devuelve propiedades que utiliza la página en cuestión.

Por ejemplo, si queremos alimentar nuestra página con información de una planta, getStaticProps nos permite definir qué propiedades (props) necesita React para renderizar la página correctamente.

export async function getStaticProps(context) {
  const data = await fetch('https://miapi.com/planta');
  const planta = await data.json();

  return {
    props: {
      planta,
    },
  };
}

Aquí, recuperamos los datos de una API y los pasamos como propiedades que usará la página.

¿Qué es Get Static Paths y cómo se utiliza?

Cuando te encuentras gestionando páginas dinámicas, como entradas de blogs con slugs dinámicos en sus URLs, getStaticPaths es tu aliado. Este método complementa a getStaticProps y le dice a Next.js qué rutas dinámicas necesitamos generar en el momento de la construcción.

¿Cómo definir los caminos con getStaticPaths?

  • Define qué rutas se deben construir estáticamente.
  • Utiliza un array donde cada elemento es un objeto que contiene las propiedades necesarias para cada página.
export async function getStaticPaths() {
  const res = await fetch('https://miapi.com/plantas');
  const plantas = await res.json();

  const paths = plantas.map((planta) => ({
    params: { slug: planta.slug },
  }));

  return { paths, fallback: false };
}

En el ejemplo, se traen las plantas desde una API, generando un array de rutas que Next.js usará para crear esas páginas en el build time.

¿Cómo mejorar la escalabilidad de nuestras páginas?

El uso combinado de getStaticProps y getStaticPaths proporciona eficiencia, pero, como cualquier estrategia, tiene sus limitaciones. Por ejemplo, la necesidad de definir todas las rutas en build time puede presentar problemas si el número de páginas crece enormemente. Para abordar esta limitación:

  1. Optimización de Peticiones: Utilizar límites en peticiones API para no cargar más información de la necesaria.
  2. Validación de Slugs: Implementar validaciones para asegurar que los slugs dinámicos sean correctos y prevenir errores en las rutas.
  3. Pruebas Efectivas: Realizar pruebas para visualizar el desempeño de la aplicación y ajustar las configuraciones de build si es necesario.

Explora todo el potencial de Next.js

La capacidad de generar páginas de manera estática es solo una de las muchas características avanzadas de Next.js. Para profundizar y dominar estas técnicas, considera explorar cursos que cubren desde fundamentos hasta aspectos técnicos avanzados. ¡Nunca dejes de aprender y experimentar con nuevas estrategias para mejorar la experiencia y el rendimiento de tus proyectos!

Aportes 5

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Dejo esto acá para mi yo del futuro😐

query GetPlantList{
  plantCollection(limit:10, skip:20){
    total
    skip
    limit
    items{
      slug
    }
  }
}
    <Layout>
        <Grid container spacing={4} >
            <Grid item xs={12} md={8} lg={9} component="article">
                <figure>
                    <img width={952} src={plant.image.url} alt={plant.image.title} />
                </figure>
                <div className="px-12 pt-8">
                    <Typography variant="h2">{plant.plantName} </Typography>
                </div>
                <div className="p-10">
                    <RichText richText={plant.description} />
                </div>
            </Grid>
            <Grid item xs={12} md={4} lg={3} component="aside">
                <section>                    
                    <Typography variant="h5" component="h3" className="mb-4" > 
                        Recent post
                    </Typography>
                </section>
                {otherEntries?.map((plantEntry) => (
                    <article className='mb-4' key={plantEntry.id}>
                        <PlantEntryInline {...plantEntry}/>
                    </article>
                ))}
                <section className='mt-10'>
                    <Typography variant="h5" component="h3" className='mb-4'>
                        Categories
                    </Typography>
                    <ul className='list'>
                        {categories?.map((category) => (
                        <li key={category.id}>
                            <Link passHref href={`/category/${category.slug}`}>
                                <Typography variant="h6" component="a">
                                    {category.title}
                                </Typography>
                            </Link>                                 
                        </li>
                        ))}
                    </ul>
                </section>
            </Grid>
        </Grid>
        <section className='my-4 border-t-2 border-b-2 border-gray-200 pt-12 pb-7'>
            <AuthorCard {...plant.author} />
        </section>
    </Layout>

También estaba pensando en esa desventaja mencionada al final de la clase. Qué pasaría con blogs que superen los 500 blogposts? (por poner un número)

El resultado final del código:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router'
import {getPlantList, getPlant, QueryStatus, getCategoryList } from '@api'
import { Layout } from '@components/Layout';
import { Typography } from '@material-ui/core';
import { Grid } from '@ui/Grid'
import { PlantEntryInline } from '@components/PlantCollection';
import { RichText } from '@components/RichText'
import { AuthorCard } from '@components/AuthorCard'
import { GetStaticProps, InferGetStaticPropsType } from 'next';
import Link from 'next/link';

// Definición del tipo para el Path que se utiliza en getStaticPaths.
type PathType = {
    params: {
        slug: string
    }
}

// Esta función determina todas las rutas que se pre-renderizarán en tiempo de construcción.
export const getStaticPaths = async () => {
    // Aquí obtenemos la lista de plantas para luego generar las rutas.
    const entries = await getPlantList({limit:10})

    // Creamos la lista de rutas a partir de la lista de plantas.
    const paths: PathType[]= entries.map(plant => ({
        params: {
            slug: plant.slug
        } 
    }))

    // Devolvemos la lista de rutas y establecemos el fallback en false, lo que significa que si se intenta acceder a una ruta que no está en la lista, se mostrará una página 404.
    return {
        paths,
        fallback: false
    }
}

// Definición de los props para este componente.
type PlantEntryProps = {
    plant: Plant | null
    otherEntries: Plant[] | null
    categories: Category[] | null
}

// Esta función se encarga de obtener los datos necesarios para pre-renderizar la página.
export const getStaticProps: GetStaticProps<PlantEntryProps> = async ({ params }) => {
    const slug = params?.slug;

    // Comprueba si el slug es de tipo string, si no, devuelve notFound.
    if (typeof slug !== 'string'){
     return { notFound: true }   
    }

    // Intenta obtener los datos de la planta, otras entradas y categorías. Si falla, devuelve notFound.
    try{
        const plant = await getPlant(slug)
        const otherEntries = await getPlantList({ limit: 5})
        const categories = await getCategoryList({ limit: 10})
        
        return {
            props: {
                plant,
                otherEntries,
                categories
            }
        } 
    }catch(error) {
        return {
            notFound: true
        }
    }
}

// Definición del componente principal de la página de entrada de la planta.
export default function PlantEntryPage({
    plant,
    otherEntries,
    categories,
}: InferGetStaticPropsType <typeof getStaticProps>) {

    // Renderiza la página con la información de la planta, otras entradas y categorías.
    return(
        <Layout>
            <Grid container spacing={4} >
                <Grid item xs={12} md={8} lg={9} component="article">
                    <figure>
                        <img width={952} src={plant.image.url} alt={plant.image.title} />
                    </figure>
                    <div className="px-12 pt-8">
                        <Typography variant="h2">{plant.plantName} </Typography>
                    </div>
                <div className="p-10">
                    <RichText richText={plant.description} />
                </div>
            </Grid>

            {/*Esta sección se encarga de renderizar el aside del layout.*/}
            <Grid item xs={12} md={4} lg={3} component="aside">
                <section>                    
                    <Typography variant="h5" component="h3" className="mb-4" > 
                        Recent post
                    </Typography>
                </section>

                {/*Aquí mapeamos y renderizamos las otras entradas de plantas obtenidas.*/}
                {otherEntries?.map((plantEntry) => (
                    <article className='mb-4' key={plantEntry.id}>
                        <PlantEntryInline {...plantEntry}/>
                    </article>
                ))}

                {/*Sección para renderizar las categorías.*/}
                <section className='mt-10'>
                    <Typography variant="h5" component="h3" className='mb-4'>
                        Categories
                    </Typography>
                    <ul className='list'>
                        {/*Mapeamos y renderizamos las categorías obtenidas.*/}
                        {categories?.map((category) => (
                        <li key={category.id}>
                            {/*Aquí utilizamos el componente Link de Next.js para crear enlaces a las páginas de las categorías.*/}
                            <Link passHref href={`/category/${category.slug}`}>
                                <Typography variant="h6" component="a">
                                    {category.title}
                                </Typography>
                            </Link>                                 
                        </li>
                        ))}
                    </ul>
                </section>
            </Grid>
        </Grid>

        {/*Sección para renderizar la tarjeta del autor de la planta.*/}
        <section className='my-4 border-t-2 border-b-2 border-gray-200 pt-12 pb-7'>
            <AuthorCard {...plant.author} />
        </section>
    </Layout>
    )
}

SSG

Es la forma en que se genera paginas estaticas en build time.

  • Gracias a la funcion getStaticPaths() obtenemos un array con los slugs que se necesitarán para crear una pagina dinámica.
  • En la funcion getStaticProps() obtiene los params(como props) y hace uso de este para hacer una query con ese slug para así obtener la informacion de una planta en específico.