Escuela Frontend
React

La Guía Definitiva de GraphQL y Como Usarlo en tu Próxima Aplicación de React

Mateo García
Autor
Mateo García

La interacción entre frontend y backend es una de las características principales con las que cuentan la mayoría de sitios y aplicaciones web. La comunicación entre cliente y servidor a través de una API le permite al cliente (frontend) obtener y editar la información almacenada en una base de datos, los datos persisten y están disponibles para ser entregados a través de un servidor REST (backend), usando el protocolo HTTP.

Desde el frontend, el consumo de servicios REST es muy comúnmente usado, sin embargo, los problemas aparecen cuando el frontend necesita tener más control sobre las peticiones, obtener una propiedad adicional de la base de datos, ordenar los resultados, u obtener múltiples recursos al mismo tiempo.

Todos estos cambios mencionados implican trabajo que hacer, el backend debe de escribir más código, realizar iteraciones y los cambios en el frontend no se detienen.

Aquí es donde GraphQL viene a brillar por la facilidad y flexibilidad con la que esos cambios pueden ser realizados sin tocar una sola línea de código en el backend.

Cuando termines de leer este artículo entenderás en qué consisten los servicios en GraphQL, cuál es su lenguaje y cómo consumir servicios GraphQL desde una aplicación React. También conocerás las diferentes alternativas que el Open Source nos ofrece para crear clientes desde React y cuáles son algunas de sus características.

Una porción muy grande de las aplicaciones consumen información a través de servicios web, primero estuvieron los servicios SOAP, después los servicios REST, y ahora, la migración a servicios GraphQL está ocurriendo y no saber cómo funcionan puede generar incertidumbre, bugs, o simplemente no poder participar en un proyecto.

La comunicación entre cliente y servidor ocurre día a día en las actividades de un desarrollador frontend, es fundamental entender la filosofía y lenguaje que ha diseñado el equipo de GraphQL para entender los beneficios que trae para nosotros.

Este artículo está diseñado para desarrolladores web que están interesados en aprender los últimos estándares y en reducir el nivel de complejidad que significa obtener datos desde un servidor. Tendrás una guía básica sobre GraphQL e incluso verás ejemplos de cómo usar sus características principales desde React.

Contenido del post

  1. ¿Qué es GraphQL?
  2. Operaciones básicas
    1. La consola de GraphQL
    2. Query en GraphQL
    3. Mutation
    4. Subscription
  3. React y GraphQL
    1. Introducción a Apollo Client
    2. Ejecutando Query
    3. Ejecutando Mutation
  4. Alternativas para Apollo
  5. Conclusiones

¿Qué es GraphQL?

GraphQL es una especificación que establece patrones para comunicar un cliente y un servidor, ofrece una arquitectura nueva para desarrollar APIs usando las mejores prácticas de la industria. Fue desarrollada en 2012 por un equipo interno de Facebook y publicada como open source en 2015, al ser una especificación se puede usar en cualquier lenguaje de programación o framework.

Estas son algunas de sus características principales.

  • Facilita la agrupación de múltiples peticiones en una solicitud: Ejecutar diferentes requests desde el cliente es cosa del pasado, con GraphQL es posible obtener múltiples recursos en una sola petición.
  • Permite ser flexible y explícito a la hora de obtener datos: Con GraphQL, quien tiene el control es el cliente, no el servidor. El frontend tiene el poder de pedir solo los datos que requiere, de esa forma, los requests son más precisos y menos costosos.
  • Es de tipado seguro y se documenta automáticamente: Cada recurso está definido a través de un esquema, el cual es representado interactivamente como documentación de la API.
  • Elimina la necesidad de tener URLs para llamar a los servicios: No más endpoints guardados en constantes, todos los recursos están disponibles a través de queries, mutations y subscriptions.

Operaciones básicas

Las operaciones nos permiten establecer una interacción entre el cliente y el servidor, desde el cliente es posible requerir y modificar información que está en el servidor.

Diagrama de operaciones en GraphQL

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070243/articles/GraphQL-react/graphql_operations_nfvvmc.png

La consola de GraphQL

Uno de los beneficios que tiene GraphQL es que nos facilita la interacción entre el cliente y el servidor. Es por eso que nos entrega una consola interactiva que permite diseñar y preparar las operaciones antes que el cliente las ejecute.

Consola de GraphIQL, una vista interactiva de los requests.

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070243/articles/GraphQL-react/graphiql_console_bhivwo.png

Esta consola que acabas de ver se llama GraphIQL, es parte del setup que hace el servidor que usamos para este ejemplo y, dependiendo de los paquetes, la consola puede cambiar.

El panel 1 nos permite escribir todas las operaciones que necesitemos.

El panel 2 nos muestra el resultado de las operaciones ingresadas.

El panel 3 nos enseña la documentación generada automáticamente por el type system de GraphQL, como puedes ver, definimos dos recursos, Book y Movie.

Query

Cuando un sitio o aplicación necesita datos que están en el servidor, realiza una operación de lectura, así, el cliente le especifica al servidor los parámetros de los datos que quiere obtener y el servidor le responde con los datos correspondientes.

Escribamos nuestra primera Query requiriendo datos de todos los libros y películas.

query {
allBooks {
id
name
author # Puedes incluir todas las propiedades
category # del recurso, o solo las que necesites
}
allMovies {
id
name
category
}
}

La consola de GraphQL que estás viendo y los esquemas de Book y Movie se definen desde un servidor backend, una vez tu servidor esté listo podremos hacer uso de cada operación implementada.

La consola de GraphQL respondiendo a una solicitud

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070244/articles/GraphQL-react/graphql_query_dcwcqi.png

Algunos aspectos importantes de la solicitud anterior:

  • Se están pidiendo múltiples recursos (Books y Movies). Si necesitaramos incluir uno nuevo como Pictures podríamos hacerlo fácilmente.
  • Cada uno de los recursos tiene propiedades adicionales que podrían ser obtenidas, sin embargo, este query demuestra la flexibilidad que tiene GraphQL para obtener solo los datos que se necesitan.

Mutation

Uno de los objetivos de comunicar el cliente y el servidor es establecer mecanismos para modificar los datos que el servidor expone. La creación, edición o eliminación de un registro de la base de datos es lo que llamaremos a nivel de operaciones de GraphQL como una mutación.

Definamos nuestra primera Mutation eliminando un registro de los libros:

mutation {
removeBook(id: "2") {
id
name
author
category
}
}

removeBook usa el id del recurso para eliminarlo, seleccionamos uno en particular para el ejemplo (id: "2"). Si le echamos un vistazo a la consola, la respuesta será esta:

La consola de GraphQL respondiendo a un Mutation

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070244/articles/GraphQL-react/graphql_mutation_kntg5k.png

Si ejecutamos un nuevo query solo para los libros, observaremos que el libro con el id: "2" ya no estará disponible:

La consola de GraphQL respondiendo a una Query después de un Mutation

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070244/articles/GraphQL-react/graphql_mutation_query_kpthok.png

Subscription

Las suscripciones son peticiones de larga duración, el servidor constantemente está entregando información al cliente a medida que esta varía. Las suscripciones pueden ser usadas en sitios o aplicaciones web donde los datos cambian constantemente y es muy importante mostrarlos siempre actualizados.

Existen diferentes maneras de implementar Subscriptions, pero la estrategia más popular es a través de Websockets. Estos son algunos de los casos en los que las suscripciones serían de gran utilidad:

  1. Un dashboard en tiempo real de divisas.
  2. Un feed de posts que tiene interacción con likes.
  3. Un sitio para comprar productos sujetos a disponibilidad.

De manera general, estas son las operaciones básicas que nos ofrece GraphQL para interactuar entre el frontend y el backend, si aún te quedan dudas sobre cuál debes usar, ten en cuenta que:

  • Si vas a leer datos, puedes usar Query.
  • Si vas a editar, modificar o eliminar datos, puedes usar Mutation.
  • Si vas a leer o modificar datos que deben actualizarse en tiempo real, puedes usar Subscription.

React y GraphQL

Ahora que entiendes los fundamentos de GraphQL, cómo funciona su especificación y cuales son los beneficios que nos ofrece, es el momento de aprender a usarlo en React. Uno de los stacks más populares para usar GraphQL es a través de React y Apollo Client, vamos a echarle un vistazo.

Introducción a Apollo Client

Apollo Client es una librería que nos permite, desde un cliente, leer, modificar y cachear información de un servidor GraphQL. Se caracteriza por tener un API sencilla, ofrecer una solución simple para el manejo de la caché y exponer su implementación a través de React Hooks.

Para empezar a usarlo ejecutaremos npm i @apollo/client.

Luego, haremos el setup básico para usar React y GraphQL:

import React from "react";
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";
/*
1. Creamos el cliente de Apollo que será usado por el Proveedor
1.1 Le suministramos el endpoint al cual queremos conectarnos
1.2 Le pasamos un módulo que se encargue de manejar la caché
*/
const client = new ApolloClient({
uri: "http://localhost:3001",
cache: new InMemoryCache(),
});
/*
2. Usamos ApolloProvider que crear un contexto del cliente de Apollo
2.1 ApolloProvider requiere el cliente que creamos previamente
2.2 Todos los elementos/componentes hijos de ApolloProvider
podrán hacer uso del cliente de Apollo
*/
function App() {
return (
<ApolloProvider client={client}>
<h1>¡Hola Escuela Frontend!</h1>
</ApolloProvider>
);
}

Ahora que hemos configurado @apollo/client estamos listos para ejecutar operaciones desde React.

Ejecutando Queries

Para ejecutar un Query, lo primero que debes hacer es diseñarlo con la información que deseas obtener, puedes hacer uso de la consola de GraphQL, a continuación verás un componente de React renderizar datos obtenidos desde un servidor:

import React from "react";
import { gql, useQuery } from "@apollo/client";
/*
1. Diseñamos el Query que queremos ejecutar
1.1 `gql` es un método que serializa nuestro query
1.2 Dentro de él estará la información que vamos a recibir
*/
const ALL_MOVIES = gql`
query {
allMovies {
id
name
director
category
}
}
`;
function MoviesList() {
/*
2. Usamos useQuery, el hook de Apollo Client para leer datos remotos
2.1 Le pasamos ALL_MOVIES a useQuery y el nos retorna data, loading, error
2.2 Con estos tres valores podremos:
2.2.1 error - Validar si hay un error en el resultado de la operación
2.2.2 loading - Validar si la operación está en proceso o ya ha terminado
2.2.3 data - Obtener los datos y usarlos en nuestro componente
*/
const { error, loading, data } = useQuery(ALL_MOVIES);
if (error) return <p>{error.message}</p>;
if (loading) return <p>Loading...</p>;
return (
<ul>
{data.allMovies.map((movie) => (
<li>
{/*...movie*/}
</li>
))}
</ul>
);
}

Mientras la operación esté en proceso podremos indicarle al usuario que se está cargando:

Un texto de loading que aparece mientras la petición está en proceso

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070244/articles/GraphQL-react/query_react_loading_alj7ha.png

Cuando la operación haya finalizado exitosamente renderizamos los datos obtenidos:

Una lista de tarjetas con el resultado de buscar todos los libros

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070244/articles/GraphQL-react/query_react_result_as10eh.png

Finalmente, cuando ocurre un error podremos notificarlo adecuadamente:

Un mensaje de error con la razón.

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070242/articles/GraphQL-react/query_react_error_ifflrs.png

Ejecutando Mutation

Al igual que en la sección de Query, lo primero que podemos hacer para obtener los datos del servidor, es interactuar con la consola de GraphQL. En está ocasión usaremos un Mutation para eliminar un elemento de Movies.

import React from "react";
import { gql, useQuery, useMutation } from "@apollo/client";
/*
1. Diseñamos el Mutation que queremos ejecutar
1.1 Query y Mutation reciben argumentos, como una función
1.2 $id será suministrado a través de useMutation
1.3 Con el id el servidor podrá remover el elemento
*/
const REMOVE_MOVIE = gql`
mutation RemoveMovie($id: ID!) {
removeMovie(id: $id) {
id
}
}
`;
function MoviesList() {
const { error, loading, data } = useQuery(/*...*/);
/*
2. Usamos useMutation, el hook de Apollo Client para modificar datos remotos
2.1 useMutation recibe a REMOVE_MOVIE, luego el nos retorna un arreglo con:
2.1.1 Una función actualizadora, que se puede ejecutar programáticamente, esta función recibe las variables con las que la mutación ocurrirá.
2.1.2 Un objeto con el resultado de la mutación (data, loading, error).
*/
const [removeMovie] = useMutation(REMOVE_MOVIE);
if (error) return <p>{error.message}</p>;
if (loading) return <p>Loading...</p>;
/*
3. Declaramos un manejador de eventos el cual:
3.1 Obtiene el id de la tarjeta que se quiere eliminar
3.2 Llamará a la función actualizadora pasandole el id que vamos a eliminar
*/
function onTrashClick(evt) {
const { currentTarget } = evt;
const { id } = currentTarget;
removeMovie({
variables: {
id,
},
});
}
return (
<>
<h1>Movies List</h1>
<ul>
{data.allMovies.map((movie) => (
<li key={movie.id}>
{/* ...movie */}
<button id={movie.id} onClick={onTrashClick}>
<FaTrash />
</button>
</li>
))}
</ul>
</>
);
}

Si eliminamos el siguiente elemento:

Tarjetas de películas, seleccionando el id 3 para ser eliminado

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070243/articles/GraphQL-react/mutation_react_lb88ip.png

Y luego refrescamos el navegador, veremos que el id número tres ya no estará disponible:

Tarjetas de películas sin el elemento que acabamos de eliminar

https://res.cloudinary.com/escuela-frontend/image/upload/v1634070242/articles/GraphQL-react/mutation_react_after_delete_xrbfit.png

Alternativas a Apollo Client

Tal vez Apollo Client no sea la mejor herramienta para tu equipo, y es importante estar abiertos a intentar diferentes alternativas y ver cuál biblioteca es la mejor para solucionar un problema específico, si buscas alternativas para @apollo/client te dejo varias librerías que podrían ser útiles:

React Query

React Query es un cliente para manejar datos remotos y es agnóstico a la arquitectura del servidor que se va a consumir (sea REST o GraphQL), reduce el boilerplate que supone consumir datos desde uno o múltiples servidores, favorece la escalabilidad de las aplicaciones y se preocupa por el performance y la experiencia de uso en la aplicación.

Documentación oficial Peso en GZIP: 12.3K

urql es un cliente de GraphQL que promete ser versátil y configurable, sus principales beneficios incluyen facilidad para ser usado, solución de caching por default y facilidad para ser extendido.

Este cliente ofrece soporte para React, Vue, Svelte y Vanilla Javascript.

Documentación oficial Peso en GZIP: 8.2K

Relay

Relay se define como el cliente GraphQL que escala contigo, es el cliente oficial de Facebook, busca mantener las iteraciones de software rápidas, ofrece optimizaciones por defecto y mantiene la consistencia de datos a lo largo de toda la aplicación.

Documentación oficial Peso en GZIP: 36k

Conclusiones

Usar servicios GraphQL puede impactar positivamente a todos los equipos detrás de un producto, los tiempos de desarrollo pueden reducirse, el número de bugs puede reducirse y el entendimiento de la capa de datos puede ser más claro.

GraphQL no es una bala de plata, no todos los proyectos deben ser creados o migrados a GraphQL, como equipo es importante identificar las soluciones que hay en el mercado y tomar la mejor decisión para el producto. Sin embargo, los esfuerzos aprovechados en optimizar la arquitectura, las soluciones out of the box y la facilidad para integrarse con aplicaciones son algunas de las razones por las cuales empresas como Github, Facebook o Shopify han tomado la decisión de usarlo en producción.

Si quieres practicar con un servidor GraphQL de prueba puedes usar alguna de estás opciones:

  • Puedes usar alguna API de fácil acceso, este sitio compila una lista de servidores que pueden ser usados.
  • Tambien puedes usar json-graphql-server, te permite configurar un servidor GraphQL dummy, y ejecutar queries y mutaciones.

En caso de que quieres echarle un vistazo al código de los ejemplos puedes encontrar el proyecto en este enlace 🧑‍💻

Este ha sido un gran recorrido, espero que este artículo te haya servido. Te deseo muchos éxitos en tu carrera como Frontend y gracias por leerme.

Artículos Relacionados

¿Quieres mejorar tus habilidades de frontend?