¿Alguna vez has tenido que renderizar diferentes componentes dependiendo de si tu aplicación esta caragando datos o ha ocurrido un error? Si es asi o quieres aprender a hacerlo, este articulo es para ti.
En el desarrollo de los proyectos actuales es común el uso de peticiones asíncronas evitando bloquear el portal mientras se obtienen los datos que se desean visualizar. En JavaScript hacemos el uso de nuestra vieja librería amiga llamada axios o utilizamos la nueva API de los exploradores fetch. Veamos un ejemplo utilizando React.
Si quieres saber más sobre Fetch API y la programación asíncrona, tenemos un excelente video: Fetch API en JavaScript (GET, POST, PUT, DELETE)
import React, {useState, useEffect} from 'react' export default function App() { const [data, setData] = useState([]) // componentDidMount useEffect(() => { // Obteniendo datos de API fetch('https://rickandmortyapi.com/api/character') .then(res => res.json()) // Almacenando los datos en el estado data .then(data => setData(data)) }) // El resto de nuestro componente... }
Hasta ahora todo es muy sencillo y no parece tener muchos problemas, pero pensemos en algunas circunstancias.
Primero, debemos hacerle saber al usuario que los datos se están cargando y del mismo modo debemos hacerle saber al usuario si algo malo sucedió y es imposible mostrarle los datos, como un error 500.
Para lograr esto creamos el estado de isLoading y el estado de error.
import React, {useState, useEffect} from 'react' export default function App() { const [data, setData] = useState([]) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(false) // componentDidMount useEffect(() => { // Informamos que estamos cargando los datos setIsLoading(true) // Obteniendo datos de API fetch('https://rickandmortyapi.com/api/character') .then(res => res.json()) .then(data => { // Informamos que ya se terminó de cargar setIsLoading(false) // Almacenando los datos en el estado setData(data) }) .catch(e => { // Asignamos el error en caso de que exista. setError(e) }) } // El resto de nuestro componente... }
En la gran mayoría de ocasiones este código se vuelve repetitivo por lo que usualmente podríamos pensar primero; en refactorizar o segundo, usar alguna herramienta como redux-saga para controlar estas peticiones.
Teniendo esto en mente Tanner Linsley creó una librería llamada ReactQuery, veamos como sería el mismo ejemplo pero con ReactQuery.
Primero es necesario instalar la librería.
$ npm i react-query # or $ yarn add react-query
Ahora hagamos uso de useQuery, que es un hook que nos permite realizar las peticiones, este hook al menos debe recibir como parámetros; un identificador y la función asíncrona que utilizaremos para solicitar la información.
import React from ‘react’ import { useQuery } from ‘react-query’ export default function App() { const info = useQuery('obtenerPersonajes', () => fetch('https://rickandmortyapi.com/api/character') .then(res => res.json()) ) // Veamos en consola. console.log(info); // El resto de nuestro componente... }
useQuery nos devuelve un objeto con toda la información que necesitamos.
{ "status": "loading", "isLoading": true, "isSuccess": false, "isError": false, "isIdle": false, "data": undefined, "error": null, "canFetchMore": undefined }
Podemos observar que tiene parámetros como status
, isLoading
o error
, con ello en mente podemos deconstruir el objeto y listo; así de sencillo podemos contar con la misma funcionalidad que en el ejemplo anterior.
Si quieres entender mejor qué significa deconstruir te recomendamos el curso de JavaScript para React
import React from ‘react’ import { useQuery } from ‘react-query’ export default function App() { const { data, isLoading, isError, error } = useQuery( 'obtenerPersonajes', () => fetch('https://rickandmortyapi.com/api/character') .then(res => res.json()) ) if (isLoading) return 'Cargando…' if (isError) return `Error: ${error}` return data; }
Como podemos observar, ReactQuery nos brinda una interfaz muy sencilla para poder realizar peticiones asíncronas ofreciendo una mejor legibilidad a nuestro código.