No tienes acceso a esta clase

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

Moviendo al servidor: getStaticProps

9/19
Recursos

Aportes 5

Preguntas 3

Ordenar por:

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

o inicia sesión.

getStaticProps

nos funciona cuando requerimos que nuestra aplicacion sea SEO friendly. Dado que los SPA o client-side rendering no generan contenido, esta tecnica nos ayuda a que nuestro sitio en Next.js sea encontrado por Google.

Recuerden importar GetStaticProps y InferGetStaticPropsType desde Next

Explicación del código

// Estas son las importaciones de los diferentes componentes y funciones que se utilizarán en el archivo.
import { Layout } from '@components/Layout'
import { getPlantList } from '@api/index'
import { PlantCollection } from '@components/PlantCollection'
import { GetStaticProps , InferGetStaticPropsType } from 'next'
import { Hero } from '@components/Hero'
import { Authors } from '@components/Authors'

// Aquí estás definiendo un tipo para los props de tu página de inicio. 
// De acuerdo con este tipo, espera recibir un arreglo de plantas.
type HomeProps = { plants:Plant[]}

// La función getStaticProps es una característica de Next.js que te permite pre-renderizar tu página en el momento de la construcción. 
// En este caso, estás obteniendo una lista de plantas de tu API y pasándolas como props a tu componente de página de inicio.
export const getStaticProps: GetStaticProps<HomeProps> = async () => {
  
  const plants = await getPlantList({limit:10})

  return{
    props: {
      plants
    }
  }
}

// Este es el componente de tu página de inicio. 
// Recibe las plantas como props debido a la función getStaticProps que definiste anteriormente.
export default function Home({plants}: InferGetStaticPropsType<typeof getStaticProps>) {

  return (
    // Estás envolviendo todo tu contenido de la página de inicio en un componente Layout.
    <Layout>
      // El componente Hero recibe la primera planta de tu lista de plantas como props. Le estás dando una margen inferior con la clase 'mb-20'.
      <Hero {...plants[0]} className='mb-20' />
      // El componente Authors es mostrado a continuación, también con un margen inferior definido.
      <Authors className='mb-10' />
      // El componente PlantCollection se usa para mostrar tus plantas. Primero, muestras las plantas de la posición 1 a la 3 en forma vertical con un margen inferior.
      <PlantCollection plants={plants.slice(1,3)} variant='vertical' className='mb-24'/>
      // Luego, si tienes más de 8 plantas, muestras las plantas de la posición 3 a la 9 en forma cuadrada. Si tienes menos de 8, muestras todas las plantas restantes.
      <PlantCollection 
        plants={plants.length > 8 ? plants.slice(3,9) : plants}
        variant='square'
      />
    </Layout>
  )
}

Al hacer el cambio de CSR a SSR debemos utilizar la funcion getStaticProps y retornar los props con la informacion necesaria para pasarle a la pagina.

Para mejorar la experiencia de desarrollo es útil hacer uso de los tipos GetStaticProps e InferGetStaticPropsType(importados desde next) cuya funcion es tipar la informacion enviada desde el servidor y el cliente.

pages/index.tsx

Utilizamos SSG

import { GetStaticProps, InferGetStaticPropsType } from 'next'

import { Layout } from '@components/Layout'
import { getPlantList } from '@api'
import { Hero } from '@components/Hero'
import { PlantCollection } from '@components/PlantCollection'
import { Authors } from '@components/Authors'

type HomeProps = {
  plants: Plant[]
}

export const getStaticProps: GetStaticProps<HomeProps> = async () => {
  const plants = await getPlantList({ limit: 10 })

  return {
    props: { plants },
    revalidate: 5 * 60, // once every five minutes
  }
}

export default function Home({
  plants,
}: InferGetStaticPropsType<typeof getStaticProps>) {
  return (
    <Layout>
      <Hero {...plants[0]} className="mb-20" />
      <Authors className="mb-10" />
      <PlantCollection
        plants={plants.slice(1, 3)}
        variant="vertical"
        className="mb-24"
      />
      <PlantCollection
        plants={plants.length > 8 ? plants.slice(3, 9) : plants}
        variant="square"
      />
    </Layout>
  )
}

Para el caso de components/Authors.tsx

Utilizamos Client Sire Rendering

import { useEffect, useState } from 'react'
import Link from 'next/link'
import { getAuthorList, QueryStatus } from '@api'
import { Grid } from '@ui/Grid'
import { Typography } from '@ui/Typography'

type AuthorProps = {
  className?: string
}

export function Authors({ className }: AuthorProps) {
  const { data, status } = useAuthors()

  if (data == null || status !== 'success') {
    const dummyItems = Array.from({ length: 4 }, (_, i) => `item-${i}`)
    return (
      <Grid container spacing={4} className={className} justify="center">
        {dummyItems.map((item) => (
          <Grid
            xs={2}
            item
            key={item}
            className="bg-gray-200 animate pulse"
          ></Grid>
        ))}
      </Grid>
    )
  }

  return (
    <Grid container spacing={4} className={className} justify="center">
      {data.map(({ id, photo, fullName, handle }) => (
        <Grid item key={id}>
          <Link href={`/top-stories/${handle}`}>
            <a title={`See latest stories from ${fullName}`}>
              <img src={photo.url} width={150} />
              <Typography variant="h5" component="p">
                {fullName}
              </Typography>
            </a>
          </Link>
        </Grid>
      ))}
    </Grid>
  )
}

function useAuthors() {
  const [status, setStatus] = useState<QueryStatus>('idle')
  const [data, setData] = useState<Author[] | null>(null)

  useEffect(
    () => {
      setStatus('loading')
      getAuthorList({ limit: 10 })
        .then((returnedData) => {
          setData(returnedData)
          setStatus('success')
        })
        .catch(() => setStatus('error'))
    },
    [
      // Run effect once
    ]
  )

  return {
    status,
    data,
  }
}