Repasemos las cinco mejores formas en que puede obtener datos con React desde una API GraphQL

Si bien hay un par de bibliotecas populares que están diseñadas para interactuar con las API de GraphQL desde una aplicación React, hay muchas formas diferentes de obtener datos con GraphQL.

He incluido ejemplos de código que le muestran cómo buscar o "consultar" datos en el código más corto posible y cómo empezar a trabajar con cada uno de estos diferentes métodos para conectar React con GraphQL.

Empezamos

En estos ejemplos, usaremos la API de SpaceX GraphQL para buscar y mostrar las últimas 10 misiones que SpaceX ha realizado.

Siéntete libre de usar el código a continuación si está intentando conectar tu aplicación React con una API GraphQL. En estos ejemplos, vamos a pasar de la biblioteca cliente GraphQL más avanzada para React al enfoque más simple para consultar un endpoint GraphQL.

1. Apollo Client

La biblioteca GraphQL más popular y completa es Apollo Client.

No solo puedes usarlo para obtener datos remotos con GraphQL, lo que estamos haciendo aquí, sino que nos permite administrar datos localmente, tanto a través de una caché interna como de una API de administración de estado completa.

Para comenzar con Apollo Client, debe instalar tanto la dependencia principal de Apollo Client como GraphQL:

npm install @apollo/client graphql

La idea detrás de Apollo Client es que se utilizará en toda tu aplicación. Para hacer esto, usará un componente Apollo Provider especial para pasar un cliente de Apollo creado a todo su árbol de componentes.

Cuando creas tu cliente Apollo, debes especificar un valor uri, es decir, un endpoint GraphQL. Además, debe especificar un caché.

Apollo Client viene con su propia memoria caché, que se utiliza para almacenar en caché o almacenar y administrar localmente sus consultas y sus datos relacionados:

import React from "react";
import ReactDOM from "react-dom";
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";

import App from "./App";

const client = new ApolloClient({
  uri: "https://api.spacex.land/graphql/",
  cache: new InMemoryCache()
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  rootElement
);

Una vez que hayas configurado el Provider y el cliente dentro de su componente App, puedes usar todos los diferentes enlaces de React que Apollo Client te brinda para todas las diferentes operaciones de GraphQL. Estos incluyen consultas, mutaciones y suscripciones. Incluso puedes usar el Apollo Client creado directamente usando un hook personalizado llamado useApolloClient.

Ya que solo estás consultando datos aquí, usarás el hook useQuery.

Incluirás una consulta GraphQL como primer argumento para escribir su consulta. Utilizarás la función gql, que hace una serie de cosas, como darle resaltado de sintaxis del editor y la funcionalidad de formateo automático si usa la herramienta Prettier para su proyecto.

Una vez que ejecutas esta consulta, recupera los valores data, loading, y error:

import React from "react";
import { useQuery, gql } from "@apollo/client";

const FILMS_QUERY = gql`
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, loading, error } = useQuery(FILMS_QUERY);

  if (loading) return "Loading...";
  if (error) return <pre>{error.message}</pre>

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

Antes de mostrar sus datos, sus misiones, debes manejar el estado de carga. Cuando se encuentra en un estado de carga, estás obteniendo la consulta desde un punto final remoto.

También debes manejar cualquier error que ocurra. Puedes simular un error si comete un error de sintaxis en su consulta, como consultar un campo que no existe. Para manejar ese error, puedes regresar y mostrar convenientemente un mensaje de error.message.

2. Urql

Otra biblioteca con todas las funciones que conecta las aplicaciones React con las API GraphQL es urql.

Intenta brindarle muchas de las características y la sintaxis que tiene Apollo a la vez que es un poco más pequeño y requiere menos código de configuración. Brinda capacidades de almacenamiento en caché si lo deseas, pero no incluye una biblioteca de administración de estado integrada como lo hace Apollo.

Para usar urql como tu biblioteca cliente GraphQL, deberás instalar los paquetes urql y GraphQL.

npm install urql graphql

Al igual que Apollo, querrás utilizar el componente dedicado Provider  y crear un cliente con su endpoint GraphQL. Ten en cuenta que no es necesario que especifiques un caché de fábrica.

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { createClient, Provider } from 'urql';

const client = createClient({
  url: 'https://api.spacex.land/graphql/',
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider value={client}>
    <App />
  </Provider>,
  rootElement
);

Muy similar a Apollo, urql te brinda hooks personalizados que manejan todas las operaciones estándar de GraphQL y, por lo tanto, tienen nombres similares.

Nuevamente, puedes usar el hook useQuery del paquete urql. Aunque en lugar de necesitar la función gql, puedes eliminarla y usar una plantilla literal para escribir su consulta.

Al llamar a useQuery, obtienes un arreglo que puedes desestructurar como una arreglo en lugar de como un objeto. El primer elemento de este arreglo es un objeto, llamado result, que te proporciona una serie de propiedades que puede desestructurar: data, fetching, y error.

import React from "react";
import { useQuery } from 'urql';

const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const [result] = useQuery({
    query: FILMS_QUERY,
  });

  const { data, fetching, error } = result;

  if (fetching) return "Loading...";
  if (error) return <pre>{error.message}</pre>

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

De manera idéntica a la visualización de los datos que obtienes con Apollo, puedes manejar tanto su error como los estados de carga mientras obtienes sus datos remotos.

3. React Query + GraphQL Request

Es importante tener en cuenta en este punto que no necesitas una biblioteca cliente GraphQL sofisticada y pesada como urql o Apollo para interactuar con tu API GraphQL, como veremos más adelante.

Las bibliotecas como Apollo y urql se crearon no solo para ayudarte a realizar todas las operaciones estándar de GraphQL, sino para administrar mejor el estado del servidor en tu cliente React a través de una serie de herramientas adicionales. Todo esto junto con el hecho de que vienen con hooks personalizados que facilitan la administración de tareas repetitivas como manejar la carga, el error y otros estados relacionados.

Con eso en mente, echemos un vistazo a cómo puedes usar una biblioteca GraphQL muy reducida para la búsqueda de datos y combinarla con una mejor manera de administrar y almacenar en caché el estado del servidor que está incorporando a tu aplicación. Puedes obtener datos de forma muy sencilla con la ayuda del paquete graphql-request.

GraphQL Request es una biblioteca que no requiere que configure un cliente o un componente Provider. Esencialmente es una función que solo acepta un endpoint y una consulta. Muy similar a un cliente HTTP, solo tienes que pasar esos dos valores y recuperar tus datos.

Ahora, si quieres administrar ese estado en tu aplicación, puedes usar una gran biblioteca que se usa normalmente para interactuar con las API Rest, pero es igualmente útil para las API GraphQL, y esa es React Query. Brinda algunos React Hooks con nombres muy similares, useQuery y useMutation, que realizan tareas idénticas a las que realizan los hooks de Apollo y urql.

React Query también te brinda un montón de herramientas para administrar el estado, junto con un componente Dev Tools integrado que te permite ver lo que se almacena en la memoria caché incorporada de React Query.

Al emparejar tu cliente GraphQL muy básico, la solicitud GraphQL, con React Query, obtiene todo el poder de una biblioteca como urql o Apollo.

Para comenzar con este emparejamiento, solo necesita instalar React Query y GraphQL Request:

npm install react-query graphql-request

Utiliza el componente Provider de React Query y crea un cliente de consulta donde puede establecer algunas configuraciones predeterminadas de obtención de datos si lo deseas. Luego, dentro de tu componente App, o cualquier componente secundario de la aplicación, puedes usar el gancho useQuery.

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { QueryClient, QueryClientProvider } from "react-query";

const client = new QueryClient();

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={client}>
    <App />
  </QueryClientProvider>,
  rootElement
);

Para almacenar el resultado de tu operación en el caché de React Query, solo necesitas darle un valor clave como primer argumento para que sirva como identificador. Esto le permite hacer referencia y extraer datos de la caché con mucha facilidad, así como recuperar o invalidar una consulta determinada para obtener datos actualizados.

Ya que está obteniendo datos de lanzamiento, llamemos a esta consulta "launches".

Una vez más, este gancho devolverá el resultado de realizar esa solicitud. Para que el segundo argumento useQuery, debes especificar cómo obtener esos datos y React Query se encargará de resolver la promesa que devuelve la solicitud GraphQL.

import React from "react";
import { request, gql } from "graphql-request";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";
const FILMS_QUERY = gql`
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return request(endpoint, FILMS_QUERY);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

Al igual que en Apollo, obtienes un objeto que puedes desestructurar para obtener los valores de los datos, así como si estás o no en el estado de carga y el estado de error.

4. React Query + Axios

Puedes usar bibliotecas de cliente HTTP aún más simples que no tienen relación con GraphQL para obtener sus datos.

En este caso, puedes utilizar la popular biblioteca axios. Una vez más, puedes emparejarlo con React Query para obtener todos los ganchos especiales y la administración del estado.

npm install react-query axios

El uso de un cliente HTTP como axios para realizar una consulta desde una API GraphQL requiere realizar una solicitud POST al endpoint de la API. Para los datos que envíes en la solicitud, tú proporcionarás un objeto con una propiedad llamada query, que se establecerá en la consulta de su película.

Con axios, necesitarás incluir un poco más de información sobre cómo resolver esta promesa y recuperar sus datos. Necesitas decirle a React Query dónde están los datos para que puedan colocarse en la propiedad data que devuelve useQuery.

En particular, recuperas los datos en la propiedad datos de response.data:

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";
const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return axios({
      url: endpoint,
      method: "POST",
      data: {
        query: FILMS_QUERY
      }
    }).then(response => response.data.data);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

5. React Query + Fetch API

La forma más fácil de todos estos diferentes enfoques para obtener datos es simplemente usar la consulta React más la fetch API.

Dado que la fetch API está incluida en todos los navegadores modernos, no necesitas instalar una biblioteca de terceros, solo necesita instalar react-query dentro de su aplicación.

npm install react-query

Una vez que tengas el cliente React Query proporcionado a toda la aplicación, puedes simplemente intercambiar su código axios con fetch.

Lo que es un poco diferente es que debe especificar un encabezado que incluya el tipo de contenido de los datos que deseas recuperar de tu solicitud. En este caso, son datos JSON.

También necesitas utilizar el método stringify en el objeto que estás enviando como su payload con una propiedad de consulta que está configurada para su consulta de películas:

import React from "react";
import axios from "axios";
import { useQuery } from "react-query";

const endpoint = "https://api.spacex.land/graphql/";
const FILMS_QUERY = `
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, isLoading, error } = useQuery("launches", () => {
    return fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ query: FILMS_QUERY })
    })
      .then((response) => {
        if (response.status >= 400) {
          throw new Error("Error fetching data");
        } else {
          return response.json();
        }
      })
      .then((data) => data.data);
  });

  if (isLoading) return "Loading...";
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

Una ventaja de usar axios sobre fetch es que maneja automáticamente los errores por ti. Con fetch, como puedes ver en el código anterior, se debe verificar un cierto código de estado, en particular, un código de estado superior a 400.

Esto significa que su solicitud se resuelve en un error. Si ese es el caso, debe lanzar manualmente un error, que será detectado por su hook useQuery. De lo contrario, si se trata de una respuesta de rango de 200 o 300, significa que la solicitud se realizó correctamente, simplemente devuelve los datos JSON y muéstralos.

Conclusión

Este artículo se dedicó a mostrarte una serie de enfoques diferentes para obtener datos de manera efectiva de una API GraphQL con React.

A partir de estas opciones, es de esperar que puedas evaluar cuál es la más adecuada para ti y tus aplicaciones. Y ahora tienes un código útil que te permitirá comenzar a usar estas herramientas y bibliotecas mucho más rápido.

Traducido del artículo de Reed Barger - How to Fetch Data in React from a GraphQL API