Filtrando datos con react-query

Compartir esta publicación

Share on facebook
Share on linkedin
Share on twitter
Share on email

En este artículo sobre react-query vamos a hablar de una de esas librerías que han crecido mucho a lo largo de este último año, y con razón. En el mundo de react, el stack react-redux es de sobras conocido, ha sido el standard de facto durante mucho tiempo hasta que los desarrolladores (incluidos los de redux), hemos visto cómo hemos utilizado redux por encima de nuestras posibilidades. Hemos intentado aplicar redux en todas las aplicaciones habidas y por haber sin preguntarnos si quiera si era útil o no. Simplemente lo conocíamos, sabíamos como funcionaba y bueno, era nuestra zona de comfort.

Eso no ha escalado tan bien como esperábamos, redux nos complicaba muchas de las acciones que buscamos hacer en nuestra aplicación, forzándonos a crear/modificar infinitas capas para añadir una única acción en la UI. Esto ha ido cambiando con el paso del tiempo, y gracias a librerías como react-query, hemos visto como redux no era la única solución, de hecho, en muchas ocasiones, no era ni una solución.

 

Que es react-query?

React-query es una librería para react (nadie se lo esperaba, eh?) que en base a unos hooks, te permitirá hacer llamadas a tu API y gestionará la cache por ti. Tan fácil como esto (ejemplo sacado de la documentación oficial):


function Example() {
   const { isLoading, error, data } = useQuery('repoData', () =>
     fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
       res.json()
     )
   )
   if (isLoading) return 'Loading...'
   if (error) return 'An error has occurred: ' + error.message
   return (
       {data.name}
       {data.description}
       👀 {data.subscribers_count}{' '}
       ✨ {data.stargazers_count}{' '}
       🍴 {data.forks_count}
   )
 }

Como se puede ver, el hook recibe 2 parámetros obligatorios: la key y una función asíncrona. La key deberá ser única por cada llamada, dado que esa será usada para cachear el resultado de la función. La función, como era de esperar, será la encargada de hacer la llamada HTTP. Aquí no debemos dejarnos llevar por la tentación y evitar crear nuestra capa service que se encargará de esa llamada y hacer los mapeos que sean necesarios.

En este artículo no vamos a entrar en cómo se usa react-query dado que su documentación es muy completa y esta muy bien explicada, además, disponen de un servidor de discord bastante activo donde pueden resolver dudas. (https://react-query.tanstack.com/overview)

 

Ejemplo práctico

En nuestro ejemplo vamos a listar unos usuarios de un backend y tenemos que poder filtrar esa lista por estado o ciudad. Para ello empezaremos con nuestra hook de useQuery:


export const useFetchUsers = (filters: FilterMap) => {
  return useQuery(
    ["users", filters],
    () => fetchUsers(filters)
  )
}

TIP: No usar directamente useQuery en tu container, mejor usarlo dentro de un hook custom y así poder reutilizarlo, entre otras cosas.

Como podemos ver, la key es una lista (https://react-query.tanstack.com/guides/query-keys), además, uno de los elementos de la lista es una variable. Esto hará que cuando los filtros cambien, la función se ejecute de nuevo.

En nuestro container pues deberemos llamar a a useFetchUsers pasándole nuestros valores para filtrar esa lista (si los hubiere). Para ello usaremos un hook realizado para la ocasión en el que persistirá los valores en la URL y los recuperará de ahí para luego pasárselos a nuestra API.


const filters = useFilters(["city", "status"]);
const users = useFetchUsers(filters.current);

El hook useFilters no es complicado de entender, por lo menos su interfaz (https://github.com/OscarGalindo/react-query-filtering-example/blob/631bcbf2cc8ceb56591a71136420c75de70f82d7/src/hooks/filters.hook.tsx). Al final es un hook que expone 1 método y los filtros actuales.

El ejemplo de leer los filtros actuales (leídos desde la URL: https://frontend/users?city=East+Tomas&status=blocked) lo tenéis en el código anterior, filters.current devuelve el filtro actual leído de la URL.

Para cambiar los filtros, el hook provee un único método que actualiza todos los filtros (no hay nada para editar/eliminar un único filtro, todavía…), esté es filters.apply(FilterMap).

En el ejemplo, hemos querido sacar los filtros a un modal para complicar un poco la UI y ver cómo funcionaría. Al final jugamos con la herencia de los componentes, el UserContainer es el que abre el modal por lo que le pasamos el método apply al Dialog:


const [showFilters, hideFilters] = useModal(() => , [filters.current])

Donde dentro tenemos un formulario que al hacer submit llamará al onApply, tan fácil como eso. El hook internamente actualizará la URL y react-query recibirá los nuevos filtros, ejecutando la query nueva con los nuevos filtros.

Como podéis ver, lo que en redux serían seguramente 5-6 ficheros, unas 5-10 acciones con sus sagas y reducers asociados, usando react-query junto con el useFilters hook son menos de 10 líneas.

 

Conclusión

El artículo a sido algo más técnico que conceptual, pero sí que hay una lección que debemos aprender, y es que no debemos dejarnos llevar por la corriente, hay que pensar las cosas, y mas en el mundo frontend donde cambia de manera muy frecuente. Es artículo no se basa en destruir redux en favor de react-query (o librerías semejantes) ni mucho menos.

En la situación del ejemplo, el estado* esta claramente en el servidor, delegamos en él la responsabilidad de todo, nosotros solo necesitamos esos datos para pintarlos y para nada más, no estamos hablando de una aplicación que pueda a llegar a funcionar offline o algún caso especial.

La clave aquí sería entender dónde queremos el estado, debería frontend tener esa responsabilidad? Debería ser compartida? Debería el backend encargarse de todo? esas son las preguntas que debemos hacernos para poder dar con la mejor herramienta.

*Estado: Cuando hablamos de estado nos estamos refiriendo no solo a los datos, sino al comportamiento de los mismos. 

  • Live example: https://react-query-filtering-example.vercel.app/
  • Repository: https://github.com/OscarGalindo/react-query-filtering-example

 

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Suscríbete a nuestro boletín de noticias

Recibe actualizaciones de los últimos descubrimientos tecnológicos

Acerca de Apiumhub

Apiumhub reúne a una comunidad de desarrolladores y arquitectos de software para ayudarte a transformar tu idea en un producto potente y escalable. Nuestro Tech Hub se especializa en Arquitectura de Software, Desarrollo Web & Desarrollo de Aplicaciones Móviles. Aquí compartimos con usted consejos de la industria & mejores prácticas, basadas en nuestra experiencia.

Posts populares

¿Tienes un proyecto desafiante?

Podemos trabajar juntos