Gatsby consumir Graphql externo y crear páginas

Mayo 17, 2021

Para este tutorial se espera que tengan un conocimiento básico en el uso de Gatsby, si no lo tienen, les recomiendo que accedan este tutorial oficial de Gatsby donde se les dará una introducción al uso de la herramienta.

En este proyecto vamos a consumir el api de Graphql de SpaceX para mostrar la lista de todos los lanzamientos que ha realizado la compañía y crearemos una plantilla para generar las páginas con el detalle de cada lanzamiento.

Para empezar vamos a crear el proyecto básico de hello world de Gatsby, recuerda tener instalado el Gatsby CLI, si no lo tienes instalado acá te muestran cómo. Luego desde la consola ejecutaremos el siguiente comando:

gatsby new gatsby-spacex-launches https://github.com/gatsbyjs/gatsby-starter-hello-world

Para probar que el proyecto se instaló correctamente, con la consola de comandos ingresamos a la carpeta gatsby-spacex-launches y ejectuamos gatsby develop para inicializar el proyecto, el cual correrá por defecto en localhost:8000.

Sitio inicial de Gatsby JS

Para poder consumir el api externo de SpaceX necesitaremos el plugin de Gatsby llamado Gatsby Source Grapqhl, para instalarlo debemos detener el proyecto y ejecutar el siguiente comando:

npm install gatsby-source-graphql

Luego configuraremos la conexion al API externo dentro del archivo gatsby-config.js de la siguiente manera:

gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options:{
        // Nombre del esquema
        typeName: "SpaceX",
        // Nombre con el que se accedera al esquema
        fieldName: "spacex",
        // Url del API 
        url: "https://api.spacex.land/graphql/"
      }
    }
  ],
}

Con esta configuración lo que estamos haciendo es indicándole a Gatsby de la existencia del API de SpaceX, por lo que Gatsby lo que hará es incluirlo dentro de su entorno de trabajo, si ejecutamos nuevamente gatsby develop y nos dirigimos a http://localhost:8000/___grapql podremos observar que el api de SpaceX ha sido integrado al esquema de Graphql de Gatsby.

Esquema de Space X integrado en el Graphql de Gatsby JS

Modificaremos el archivo index.js para listar todos los lanzamientos de Space X, para cada lanzamiento utilizaremos el component de Link.

src/pages/index.js
import { graphql, Link } from "gatsby"
import React from "react"

//El resultado de la query se almacena en la variable data que es proporcionada por Gatsby JS
export default function Home({ data }) {  
  const lanzamientos = data.spacex.launchesPast.map(({ launch_date_local, id, mission_name }) => {
    const strDate = new Date(launch_date_local).toLocaleString("es", {year:'numeric',month:'long',day:'numeric'})
    return <div key={id}>
      <Link to={`/lanzamiento/${id}`}>{mission_name}  <span>{strDate}</span></Link>
    </div>
  });
  return <div>
    <h1>Lanzamientos de SpaceX</h1>
      {lanzamientos}
  </div>
}

//Query para obtener la lista de lanzamientos de SpaceX
export const lanzamientosQuery = graphql`
  query {
    spacex {
      launchesPast {
        launch_date_local
        id
        mission_name
      }
    }
  }
`

Ejecutamos nuevamente gatsby develop y si vamos a localhost:8000 veremos la lista de los lanzamientos de SpaceX 😁. Lanzamientos de Spacex en el index

Ya tenemos la lista de lanzamientos que ha realizado SpaceX y el enlace a cada página que nos dará el detalle de cada lanzamiento, pero nos hace falta la página de detalle, para ello vamos a crear la plantilla que Gatsby utilizará para crear la página de detalle de cada uno de los lanzamientos de SpaceX.

Dentro de la carpeta ./src crearemos una nueva carpeta llamada Template y dentro de ella crearemos el archivo Lanzamiento.js

Directorio del proyecto con el archivo Lanzamiento.js

En el archivo Lanzamiento.js agregaremos el detalle con la estructura que tendrán las páginas del lanzamiento y quedará de la siguiente forma:

src/pages/Lanzamiento.js
import React from 'react'

export default function Lanzamiento({ pageContext }) {    
    return <div>
        <Link to="/">Regresar</Link>
        <h1>{pageContext.mission_name}</h1>
        <section>
            <div>
                <div>
                    <label>Fecha de Lanzamiento:</label> <span>{new Date(pageContext.launch_date_local).toLocaleString("es", { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' })}</span>
                </div>
                <div>
                    <label>Lugar de Lanzamiento:</label> <span>{pageContext.launch_site.site_name}</span>
                </div>
                <div>
                    <label>Resultado del lanzamiento:</label> <span>{pageContext.launch_success ? "Exitoso" : "Fallido"}</span>
                </div>
            </div>
            <div>
                <p>{pageContext.details}</p>
            </div>
            <div>
                {
                    pageContext.links.flickr_images.map((image, i) => {
                        return <img src={image} style={{ maxWidth: "250px", width: "100%" }} />
                    })
                }
            </div>
        </section>
    </div>
}

Ya con la plantilla de lanzamientos hecha, lo que vamos a hacer es decirle a Gatsby que utiliza la plantilla y genere la página web para cada uno de los lanzamientos de SpaceX, para ello crearemos el archivo gatsby-node.js en la raíz del proyecto de esta manera:

gatsby-node.js en el archivo raíz

Editaremos el archivo de gatsby-node.js de la siguiente manera:

exports.createPages = async ({ graphql, actions }) => {
    const { createPage } = actions
    const lanzamientoTemplate = require('path').resolve('./src/Template/Lanzamiento.js')

    const lanzamientos = await graphql(`
        query {
            spacex {
                launchesPast {
                    id
                    mission_name
                    details
                    launch_date_local
                    launch_success
                    launch_site {
                    site_name
                    }
                    links {
                    flickr_images
                    video_link
                    }
                }
            }
        }
      `)

    lanzamientos.data.spacex.launchesPast.forEach(lanzamiento => {
        createPage({
            path: `/lanzamiento/${lanzamiento.id}`,
            component: lanzamientoTemplate,
            context: {
                ...lanzamiento
            }
        })
    })
}

Volvemos a reiniciar el proyecto, vamos a localhost:8000 y hacemos click en alguno de los links deberíamos ver una página similar a esta:

Página de Lanzamiento

Por último lejos de ser un diseñador web, decidí darle unos retoques utilizando styled components y el sitio web quedó así:

Página principal con un poco de estilo

Página de Lanzamiento con un poco de estilo

Con esto hemos logrado consumir un Api de Graphql externo y logramos crear cada página basado en la información obtenida, les compartiré el proyecto en este enlace de github.


Profile picture

Blog personal de Marcos Zhu, en este espacio comparto lo que aprendo porque enseñando es la mejor forma de aprender.