Actualmente, las aplicaciones web, destacan por tener bien diferenciadas las capas: frontend, backend y datos. La comunicación entre el frontend (o interface) y el backend (o capa que implementa la lógica de negocio), es realizada a través de lo que se denomina APIs, generalmente del tipo REST. Esta es una tarea crítica y cotidiana.

Si deseas profundizar más en cuanto a los conceptos de APIs y como es posible realizar la implementación de una capa de backend te invito a revisar este artículo, acá en freeCodeCamp en Español: Construyendo una API REST con Node + Fastify + Sequelize + PostgreSQL.

Cuando implementamos aplicaciones usando ReactJS, para realizar este proceso de consumo podemos usar las funciones especiales que la librería ofrece: useState y useEffect. Si deseas verificar en forma práctica como realizar este consumo, puedes revisar este material Consumiendo APIs con ReactJS: Aprende useEffect y useState que tenemos disponible aquí en freeCodeCamp en Español.

Ahora bien, el proceso anterior puede ser un poco extenso, es por ello en las próximas líneas vamos a mostrar un paquete que tiene como propósito facilitar y simplificar el consumo de APIs REST desde React. El nombre del paquete es: React Query o como es conocido actualmente: TanStack Query.

¿Cómo instalar React Query?

Para realizar la instalación del paquete, hacemos uso de la NPM, con el siguiente comando:

npm i @tanstack/react-query

En caso de utilizar yarn como gestor de paquetes puedes usar el comando:

yarn add @tanstack/react-query

Si usas bun, el paquete ya tienen soporte, entonces la instalación se realiza con el siguiente comando:

bun add @tanstack/react-query

Instalado el paquete, lo siguiente es entender los pasos que debemos ejecutar para hacer su implementación, estos los podemos resumir de esta forma:

Habilitando el uso del paquete en la aplicación

Para dejar disponible a React Query, debemos envolver los componentes que necesiten consumir datos, su comportamiento o uso es similar a context API, en nuestro caso vamos a suponer que estamos en una aplicación pequeña, que tiene una barra de navegación (Nav), un banner o Hero, una Galería de imágenes (Gallery) y un pie o Footer, por lo que vamos a realizar este proceso a nivel de la definición de la aplicación.

Importamos los componentes necesarios:

import { QueryClientProvider, QueryClient } from '@tanstack/react-query';

Creamos una instancia del cliente QueryCliente:

const queryClient = new QueryClient();

Luego envolvemos la aplicación quedando el código del componente principal de esta forma:

const queryClient = new QueryClient();

function App() {

  return (
    <QueryClientProvider client={queryClient}>
    <div style={{display:'flex', width:'100vw', flexDirection:'column'}}>
      <NavBar></NavBar>
      <Hero></Hero>
      <Gallery></Gallery>
      <Footer></Footer>
    </div>
    </QueryClientProvider>
  )
}

Con el código anterior, ya podemos hacer uso de React Query, en cualquiera de los componentes envueltos.

Consumiendo una API REST

Para hacer uso de React Query, lo primero es hacer las importaciones necesarias dentro del componente, en este caso importamos el hook useQuery de esta forma:

import { useQuery } from '@tanstack/react-query';

Luego le definimos la configuración necesaria a useQuery colocando los siguientes parámetros:

  • queryKey, nombre o identificador de la consulta a realizar
  • queryFn, es la promesa encargada de procesar la consulta, importante tener en cuenta que se debe esperar a la ejecución, React Query hace eso por nosotros, entonces no debemos colocar await.

Al usar el hook useQuery, él nos retorna una serie de variables superútiles, veamos esto con un código de ejemplo:

  const { isLoading, data, isError, error, isSuccess } = useQuery(
            {
                queryKey: ['productos'],
                queryFn: async () => {
                    const res = await fetch('https://apiexpress-x7sl.onrender.com/productos');
                    return res.json();
                }
            });

Observemos que recibimos un objeto con propiedades que desestructuramos en la misma línea, revisemos cada una de ellas:

  • isLoading, es una variable booleana (true, false) que nos indica si la consulta está cargando datos.
  • data, son los datos retornados por la consulta, que estarán disponibles luego de la carga, es decir, cuando isLoading pase a ser false.
  • isError, otra variable booleana (true/false) que nos indica si hubo algún error a la hora de ejecutar la consulta.
  • error, almacena cualquier error que haya sucedido, importante para poder dar respuesta al usuario en caso de que no haya podido realizarse la consulta.
  • isSuccess, variable booleana que va a estar en true cuando la consulta sea realizada con éxito.

Además de las anteriores, existen otras variables que nos dan aún más información y que puedes consultar en la documentación oficial del paquete.

Aplicando useQuery en un componente real

Vamos a construir un componente que haga uso de  React Query, de acuerdo a lo indicado anteriormente. Este componente retornará un mensaje, en caso de que esté cargando los datos, un mensaje de error en caso de suceder algún problema y mostrará la data de productos consultados (porque estamos consultando una API de productos).

Veamos el componente:

import { useQuery } from '@tanstack/react-query';
import Product from '../Product/Product';



const Gallery = () => {
    
    const { isLoading, data, isError, error } = useQuery(
            {
                queryKey: ['productos'],
                queryFn: async () => {
                    const res = await fetch('https://apiexpress-x7sl.onrender.com/productos');
                    return res.json();
                }
            });
    
    if (isLoading)
        return (
            <>
                <h2>Cargando productos...</h2>
            </>
        )

    if (isError) {
        return (
            <>
                <h2>{error.message}</h2>
            </>
        )
    }
  return (
    <>
        <div className="grid place-items-center w-full bg-base-200">
            <div className="max-w-5xl py-24 content-center justify-center">
                <h1 className="text-4xl  text-center font-bold">Our Services</h1>
                <div className="grid mt-12 md:grid-cols-3 grid-cols-1 gap-8">
            
            {
                data?.map((producto) => {
                    return <Product key={producto._id} product={producto}></Product>
                })
            }
            </div>
         </div>
        </div>
    </>
  )
}

export default Gallery

Nótese que no se usan estados ni efectos secundarios (useState o useEffect), el código está completamente limpio y legible, características positivas de usar React Query para esta tarea tan crítica.

En este vídeo, puedes seguir el paso a paso de la aplicación de los conceptos anteriormente estudiados.

Si tienes alguna duda, me puedes mandar un mensaje a mi LinkedIn, con gusto te respondo.