Introducción a SWR: React Hooks para la obtención remota de datos
En este artículo, veremos una nueva forma de recuperar datos en React Apps llamada SWR. Se trata de un conjunto de enlaces para la obtención remota de datos que facilita las cosas, como el almacenamiento en caché, la paginación, etc. También crearemos una aplicación Pokedex desde cero y usaremos funciones SWR para obtener datos y paginarlos.
SWR es una biblioteca liviana creada por Vercel (anteriormente ZEIT) que permite recuperar, almacenar en caché o recuperar datos en tiempo real utilizando React Hooks. Está construido con React Suspense , que permite a sus componentes "esperar" algo antes de poder renderizar, incluidos los datos. SWR también se entrega con excelentes funciones, como búsqueda dependiente, enfoque en la revalidación, recuperación de la posición de desplazamiento, etc. También es una herramienta muy poderosa ya que es independiente del backend y tiene buen soporte para TypeScript. Es un paquete que tiene un futuro brillante.
¿Por qué debería importarte? Debería importarle si ha estado buscando una biblioteca que no solo obtenga datos de las API sino que también permita hacer cosas como el almacenamiento en caché y la recuperación dependiente. Lo que se cubrirá en este tutorial será útil al crear aplicaciones React con muchas partes móviles. Se espera que haya utilizado Axios y Fetch API, aunque compararemos en qué se diferencian de SWR, no entraremos en detalles sobre cómo se implementarán.
En esta guía, le presentaré React Hooks para la obtención remota de datos mediante la creación de una aplicación Pokedex que solicita datos de la API de Pokémon. También profundizaremos en otras características que vienen con SWR y resaltaremos sus diferencias en comparación con soluciones populares como Fetch API y la biblioteca Axios y le daremos las razones por las que usar esta biblioteca y por qué debe estar atento a SWR.
Entonces, comencemos respondiendo una pregunta fundamental: ¿Qué es la ROE?
¿Qué es la ROE?
SWR es una inicialización de obsoleto mientras se revalida. Es una biblioteca React Hooks para la recuperación remota de datos. SWR funciona con tres pasos principales: primero, devuelve los datos del caché (la parte obsoleta), luego envía la solicitud de recuperación (la parte revalidar) y finalmente viene con los datos actualizados. Pero no se preocupe, SWR se encarga de todos estos pasos por nosotros. Lo único que tenemos que hacer es darle al useSWR
gancho los parámetros necesarios para realizar la solicitud.
SWR también tiene algunas características interesantes como:
- Agnóstico de back-end
- Navegación rápida de la página
- Revalidación en foco
- sondeo a intervalos
- Solicitar deduplicación
- Mutación local
- Paginación
- Listo para mecanografiar
- Soporte RSS
- modo suspenso
- Reaccionar soporte nativo
- Ligero.
¿Suena mágico? Bueno, SWR simplifica las cosas y seguramente aumenta la experiencia de usuario de su aplicación React. Y una vez que comencemos a implementarlo en nuestro proyecto, verá por qué este gancho es útil.
Es importante saber que el nombre del paquete es swr
o SWR y el enlace utilizado para obtener las funciones de SWR se llama useSWR
.
En teoría, el SWR es quizás lo que necesita para mejorar la obtención de datos. Sin embargo, ya tenemos dos excelentes formas de realizar solicitudes HTTP en nuestra aplicación: la API Fetch y la biblioteca Axios.
Entonces, ¿por qué utilizar una nueva biblioteca para recuperar datos? Intentemos responder esta pregunta legítima en la siguiente sección.
Comparación con Fetch y Axios
Ya tenemos muchas formas de realizar solicitudes HTTP en nuestras aplicaciones React, y dos de las más populares son la API Fetch y la biblioteca Axios. Ambos son geniales y nos permiten buscar o enviar datos fácilmente. Sin embargo, una vez realizada la operación, no nos ayudarán a almacenar en caché o paginar datos, tenemos que hacerlo por nuestra cuenta.
Axios o Fetch simplemente manejarán la solicitud y devolverán la respuesta esperada, nada más.
Y en comparación con SWR, es un poco diferente porque el SWR subyacente utiliza la API Fetch para solicitar datos del servidor; es una especie de capa construida sobre él. Sin embargo, tiene algunas características interesantes como almacenamiento en caché, paginación, recuperación de la posición de desplazamiento, recuperación dependiente, etc. y, para ser precisos, un cierto nivel de reactividad lista para usar que Axios o Fetch no tienen. Es una gran ventaja porque tener estas funciones ayuda a que nuestras aplicaciones React sean rápidas y fáciles de usar y reduce notablemente el tamaño de nuestro código.
Y para concluir, tenga en cuenta que SWR no es lo mismo que Axios o Fetch, incluso si ayuda a manejar las solicitudes HTTP. SWR es más avanzado que ellos, proporciona algunas mejoras para mantener nuestra aplicación sincronizada con el back-end y, por lo tanto, aumenta el rendimiento de nuestra aplicación.
Ahora que sabemos cuáles son las diferencias que tiene SWR en comparación con la biblioteca Axios o la API Fetch, es hora de profundizar en por qué usar dicha herramienta.
Lectura recomendada : Consumir API REST en React con Fetch y Axios
¿Por qué utilizar SWR para la obtención de datos?
Como dije anteriormente, SWR incluye algunas funciones útiles que ayudan a aumentar fácilmente la usabilidad de su aplicación. Con SWR, puede paginar sus datos en poco tiempo usando useSWRPages
, también puede recuperar datos que dependen de otra solicitud o recuperar una posición de desplazamiento cuando regresa a una página determinada, y mucho más.
Por lo general, le mostramos al usuario un mensaje de carga o un control giratorio mientras recuperamos datos del servidor. Y con SWR, puede mejorarlo mostrando al usuario los datos almacenados en caché o obsoletos mientras recupera datos nuevos de la API. Y una vez realizada esa operación revalidará los datos para mostrar la nueva versión. Y no necesita hacer nada, SWR almacenará en caché los datos la primera vez que los obtenga y los recuperará automáticamente cuando se realice una nueva solicitud.
Hasta ahora, ya vemos por qué usar SWR en lugar de Axios o Fetch es mejor, dependiendo obviamente de lo que pretendas construir. Pero en muchos casos, recomendaré usar SWR porque tiene excelentes características que van más allá de simplemente buscar y devolver datos.
Dicho esto, ahora podemos comenzar a construir nuestra aplicación React y usar la biblioteca SWR para recuperar datos remotos.
Entonces, comencemos configurando un nuevo proyecto.
Configuración
Como dije anteriormente en la introducción, crearemos una aplicación que obtenga datos de la API de Pokémon. También puedes usar una API diferente si lo deseas, me quedaré con ella por ahora.
Y para crear una nueva aplicación, necesitamos ejecutar el siguiente comando en la terminal:
npx create-react-app react-swr
A continuación, debemos instalar la biblioteca SWR navegando primero a la carpeta que contiene la aplicación React.
cd react-swr
Y ejecute en la terminal el siguiente comando para instalar el paquete SWR.
yarn add swr
O si estás usando npm:
npm install swr
Ahora que hemos configurado todo, estructuremos el proyecto de la siguiente manera para comenzar a usar SWR:
src├── components| └── Pokemon.js├── App.js├── App.test.js├── index.js├── serviceWorker.js├── setupTests.js├── package.json├── README.md├── yarn-error.log└── yarn.lock
Como puede ver, la estructura de carpetas es simple. Lo único que hay que notar es la components
carpeta que contiene el Pokemon.js
archivo. Se usará más adelante como componente de presentación para mostrar un solo Pokémon una vez que obtengamos datos de la API.
¡Excelente! Una vez implementado esto, ahora podemos comenzar a obtener datos de la API usando useSWR
.
Obteniendo datos remotos
El paquete SWR tiene algunas características útiles como hemos visto anteriormente. Sin embargo, existen dos formas de configurar esta biblioteca: local o globalmente.
Una configuración local significa que cada vez que creamos un archivo nuevo, tenemos que configurar SWR nuevamente para poder recuperar datos remotos. Y una configuración global nos permite reutilizar una parte de nuestra configuración dentro de diferentes archivos porque una fetcher
función puede declararse una vez y usarse en todas partes.
Y no se preocupe, veremos ambos en este artículo, pero por ahora, pongámonos manos a la obra y agreguemos código significativo en el App.js
archivo.
Mostrando los datos
import React from 'react'import useSWR from 'swr'import { Pokemon } from './components/Pokemon'const url = 'https://pokeapi.co/api/v2/pokemon'const fetcher = (...args) = fetch(...args).then((res) = res.json())function App() { const { data: result, error } = useSWR(url, fetcher) if (error) return h1Something went wrong!/h1 if (!result) return h1Loading.../h1 return ( main className='App' h1Pokedex/h1 div {result.results.map((pokemon) = ( Pokemon key={pokemon.name} pokemon={pokemon} / ))} /div /main )}export default App
Como puede ver, comenzamos importando useSWR
desde la biblioteca SWR. Esto declara la URL de la API de la que desea obtener datos y una función para recuperar estos datos.
La función fetcher
se utiliza aquí para transformar los datos a JSON. Recibe los datos obtenidos como argumento y devuelve algo.
Observe que aquí uso el operador Rest(...args)
( ) ya que no estoy seguro del tipo y longitud de los datos recibidos como parámetro, por lo tanto, copio todo antes de pasarlo nuevamente como argumento al fetch
método proporcionado por useSWR
el cual transforma los datos. en JSON y lo devuelve.
Dicho esto, el fetcher
y el url
de la API ahora se pueden pasar como parámetros al useSWR
gancho. Con eso, ahora puede realizar la solicitud y devuelve dos estados: los datos obtenidos y un estado de error. Y data: result
es lo mismo que data.result
usamos la desestructuración de objetos para result
extraer data
.
Con los valores devueltos, ahora podemos verificar si los datos se obtuvieron correctamente y luego recorrerlos. Y para cada usuario, use el componente Pokémon para mostrarlo.
Ahora que tenemos los datos y los pasamos al Componente Pokémon, es hora de actualizar Pokemon.js
para poder recibir y mostrar los datos.
Creando el componente Pokémon
import React from 'react'import useSWR from 'swr'const fetcher = (...args) = fetch(...args).then((res) = res.json())export const Pokemon = ({ pokemon }) = { const { name } = pokemon const url = 'https://pokeapi.co/api/v2/pokemon/' + name const { data, error } = useSWR(url, fetcher) if (error) return h1Something went wrong!/h1 if (!data) return h1Loading.../h1 return ( div className='Card' span className='Card--id'#{data.id}/span img className='Card--image' src={data.sprites.front_default} alt={name} / h1 className='Card--name'{name}/h1 span className='Card--details' {data.types.map((poke) = poke.type.name).join(', ')} /span /div )}
Aquí, tenemos un componente que recibe datos únicos de Pokémon de la API y los muestra. Sin embargo, los datos recibidos no contienen todos los campos necesarios, por lo que tenemos que realizar otra solicitud a la API para obtener el objeto Pokémon completo.
Y como puedes ver, utilizamos el mismo proceso para recuperar los datos incluso si esta vez agregamos el nombre del Pokémon a la URL.
Por cierto, si no estás familiarizado con la desestructuración, ({ pokemon })
es lo mismo que recibir accesorios y acceder al objeto Pokémon con props.pokemon
. Es sólo una forma abreviada de extraer valores de objetos o matrices.
Con eso en su lugar, si navega a la carpeta raíz del proyecto y ejecuta en la terminal el siguiente comando:
yarn start
O si estás usando npm:
npm start
Deberías ver que los datos se obtienen correctamente de la API de Pokémon y se muestran como se esperaba.
¡Excelente! Ahora podemos recuperar datos remotos con SWR. Sin embargo, esta configuración es local y puede ser un poco redundante porque ya puedes verla App.js
y Pokemon.js
usar la misma función de recuperación para hacer lo mismo.
Pero afortunadamente, el paquete viene con un práctico proveedor llamado SWRConfig
que ayuda a configurar SWR globalmente. Es un componente contenedor que permite que los componentes secundarios utilicen la configuración global y, por lo tanto, la función de recuperación.
Para configurar SWR globalmente, necesitamos actualizar el index.js
archivo porque es donde se representa el componente de la aplicación usando React DOM. Si lo desea, puede usarlo SWRConfig
directamente en el App.js
archivo.
Configuración de SWR globalmente
import React from 'react'import ReactDOM from 'react-dom'import { SWRConfig } from 'swr'import App from './App'import './index.css'const fetcher = (...args) = fetch(...args).then((res) = res.json())ReactDOM.render( React.StrictMode SWRConfig value={{ fetcher }} App / /SWRConfig /React.StrictMode, document.getElementById('root'))
Como puede ver, comenzamos importando SWRConfig
cuál es un proveedor que necesita empaquetar el componente superior o solo parte de su aplicación React que necesita usar funciones SWR. Toma como accesorios un valor que espera un objeto de configuración. Puedes pasar más de una propiedad al objeto de configuración, aquí solo necesito la función para recuperar datos.
Ahora, en lugar de declarar la fetcher
función en cada archivo, la creamos aquí y la pasamos como valor a SWRConfig
. Con eso, ahora podemos recuperar datos en cualquier nivel de nuestra aplicación sin crear otra función y, por lo tanto, evitar la redundancia.
Además de eso, fetcher
es igual a fetcher: fetcher
, es solo azúcar sintáctico propuesto por ES6. Con ese cambio, ahora necesitamos actualizar nuestros componentes para usar la configuración global.
Uso de la configuración global de SWR
import React from 'react'import useSWR from 'swr'import { Pokemon } from './components/Pokemon'const url = 'https://pokeapi.co/api/v2/pokemon'function App() { const { data: result, error } = useSWR(url) if (error) return h1Something went wrong!/h1 if (!result) return h1Loading.../h1 return ( main className='App' h1Pokedex/h1 div {result.results.map((pokemon) = ( Pokemon key={pokemon.name} pokemon={pokemon} / ))} /div /main )}export default App
Ahora solo necesitamos pasar el url
método to useSWR
, en lugar de pasar el método url
and fetcher
. También modifiquemos un poco el componente Pokémon.
import React from 'react'import useSWR from 'swr'export const Pokemon = ({ pokemon }) = { const { name } = pokemon const url = 'https://pokeapi.co/api/v2/pokemon/' + name const { data, error } = useSWR(url) if (error) return h1Something went wrong!/h1 if (!data) return h1Loading.../h1 return ( div className='Card' span className='Card--id'#{data.id}/span img className='Card--image' src={data.sprites.front_default} alt={name} / h1 className='Card--name'{name}/h1 span className='Card--details' {data.types.map((poke) = poke.type.name).join(', ')} /span /div )}
Ya puedes ver que ya no tenemos función de recuperación, gracias a la configuración global que pasa la función useSWR
debajo del capó.
Ahora, puede utilizar la función de búsqueda global en todas partes de su aplicación. Lo único que useSWR
necesita el enlace para recuperar datos remotos es la URL.
Sin embargo, aún podemos mejorar la configuración creando un enlace personalizado para evitar declarar la URL una y otra vez y, en su lugar, simplemente pasar como parámetro la ruta.
Configuración avanzada mediante la creación de un gancho personalizado
Para hacerlo, debe crear un nuevo archivo en la raíz del proyecto nombrado useRequest.js
(puede nombrarlo como quiera) y agregarle este bloque de código a continuación.
import useSwr from 'swr'const baseUrl = 'https://pokeapi.co/api/v2'export const useRequest = (path, name) = { if (!path) { throw new Error('Path is required') } const url = name ? baseUrl + path + '/' + name : baseUrl + path const { data, error } = useSwr(url) return { data, error }}
Aquí, tenemos una función que recibe una ruta y, opcionalmente, un nombre y lo agrega a la URL base para crear la URL completa. A continuación, comprueba si se recibe o no un parámetro de nombre y lo maneja en consecuencia.
Luego, esa URL se pasa como parámetro al useSWR
gancho para poder recuperar los datos remotos y devolverlos. Y si no se pasa ninguna ruta, arroja un error.
¡Excelente! Ahora necesitamos modificar un poco los componentes para usar nuestro gancho personalizado.
import React from 'react'import { useRequest } from './useRequest'import './styles.css'import { Pokemon } from './components/Pokemon'function App() { const { data: result, error } = useRequest('/pokemon') if (error) return h1Something went wrong!/h1 if (!result) return h1Loading.../h1 return ( main className='App' h1Pokedex/h1 div {result.results.map((pokemon) = ( Pokemon key={pokemon.name} pokemon={pokemon} / ))} /div /main )}export default App
Ahora, en lugar de usar el gancho SWR, usamos el gancho personalizado creado sobre él y luego pasamos, como se esperaba, la ruta como argumento. Una vez implementado esto, todo funcionará como antes pero con una configuración mucho más limpia y flexible.
Actualicemos también el componente Pokémon.
import React from 'react'import { useRequest } from '../useRequest'export const Pokemon = ({ pokemon }) = { const { name } = pokemon const { data, error } = useRequest('/pokemon', name) if (error) return h1Something went wrong!/h1 if (!data) return h1Loading.../h1 return ( div className='Card' span className='Card--id'#{data.id}/span img className='Card--image' src={data.sprites.front_default} alt={name} / h1 className='Card--name'{name}/h1 span className='Card--details' {data.types.map((poke) = poke.type.name).join(', ')} /span /div )}
Ya puedes ver cómo nuestro gancho personalizado hace las cosas más fáciles y flexibles. Aquí, solo necesitamos pasar adicionalmente el nombre del Pokémon a buscar useRequest
y él se encargará de todo por nosotros.
Espero que empieces a disfrutar de esta fantástica biblioteca. Sin embargo, todavía tenemos cosas por descubrir porque SWR ofrece muchas funciones, y una de ellas es useSWRPages
un gancho para paginar datos fácilmente. Entonces, usemos ese gancho en el proyecto.
Paginar nuestros datos conuseSWRPages
SWR nos permite paginar datos fácilmente y solicitar solo una parte de ellos y, cuando sea necesario, volver a buscar datos para mostrarlos en la página siguiente.
Ahora, creemos un nuevo archivo en la raíz del proyecto usePagination.js
y usémoslo como un enlace personalizado para la paginación.
import React from 'react'import useSWR, { useSWRPages } from 'swr'import { Pokemon } from './components/Pokemon'export const usePagination = (path) = { const { pages, isLoadingMore, loadMore, isReachingEnd } = useSWRPages( 'pokemon-page', ({ offset, withSWR }) = { const url = offset || `https://pokeapi.co/api/v2${path}` const { data: result, error } = withSWR(useSWR(url)) if (error) return h1Something went wrong!/h1 if (!result) return h1Loading.../h1 return result.results.map((pokemon) = ( Pokemon key={pokemon.name} pokemon={pokemon} / )) }, (SWR) = SWR.data.next, [] ) return { pages, isLoadingMore, loadMore, isReachingEnd }}
Como puede ver, aquí comenzamos importando useSWRPages
cuál es el ayudante que permite paginar datos fácilmente. Recibe 4 argumentos: la clave de la solicitud pokemon-page
que también se usa para el almacenamiento en caché, una función para recuperar los datos que devuelve un componente si los datos se recuperan con éxito, y otra función que toma el SWR
objeto y solicita los datos de la página siguiente, y una serie de dependencias.
Y una vez que se obtienen los datos, la función useSWRPages
devuelve varios valores, pero aquí necesitamos 4 de ellos: el pages
que es el componente devuelto con los datos, la función isLoadingMore
que verifica si los datos se están recuperando actualmente, la función loadMore
que ayuda a recuperar más datos y el método isReachingEnd
que determina si todavía hay datos para recuperar o no.
Ahora que tenemos el gancho personalizado que devuelve los valores necesarios para paginar datos, ahora podemos pasar al App.js
archivo y modificarlo un poco.
import React from 'react'import { usePagination } from './usePagination'import './styles.css'export default function App() { const { pages, isLoadingMore, loadMore, isReachingEnd } = usePagination( '/pokemon' ) return ( main className='App' h1Pokedex/h1 div{pages}/div button onClick={loadMore} disabled={isLoadingMore || isReachingEnd} Load more... /button /main )}
Una vez importado el usePagination
gancho, ahora podemos pasar la ruta como parámetro y recuperar los valores devueltos. Y como pages
es un componente, no necesitamos recorrer los datos ni nada por el estilo.
A continuación, usamos la función loadMore
del botón para recuperar más datos y deshabilitarla si la operación de recuperación no finaliza o si no hay datos para recuperar.
¡Excelente! Con ese cambio, ahora podemos navegar en la raíz del proyecto e iniciar el servidor con este comando para obtener una vista previa de nuestra aplicación.
yarn start
O si estás usando npm:
npm start
Debería ver que los datos se recuperaron correctamente y, si hace clic en el botón, SWR recuperará nuevos datos.
Hasta ahora, hemos visto en la práctica la biblioteca SWR y espero que le resulte útil. Sin embargo, todavía tiene algunas características que ofrecer. Profundicemos en estas funcionalidades en la siguiente sección.
Otras características de ROE
La biblioteca SWR tiene un montón de cosas útiles que simplifican la forma en que creamos aplicaciones React.
Revalidación del enfoque
Es una característica que permite actualizar o revalidar para ser precisos los datos cuando reenfocas una página o cambias entre pestañas. Y de forma predeterminada, esta funcionalidad está habilitada, pero puedes deshabilitarla de todos modos si no se ajusta a tus necesidades. Puede resultar útil especialmente si tiene datos con actualizaciones de alta frecuencia.
Recuperar en intervalo
La biblioteca SWR permite recuperar datos después de un cierto período de tiempo. Puede resultar útil cuando sus datos cambian a alta velocidad o necesita realizar una nueva solicitud para obtener información nueva de su base de datos.
Mutación local
Con SWR, puede establecer un estado local temporal que se actualizará automáticamente cuando se obtengan nuevos datos (revalidación). Esta característica entra en juego especialmente cuando se trata de un enfoque sin conexión, ya que ayuda a actualizar los datos fácilmente.
Recuperación de la posición de desplazamiento
Esta característica es muy útil, especialmente cuando se trata de listas enormes. Le permite recuperar la posición de desplazamiento después de regresar a la página. Y en cualquier caso, aumenta la usabilidad de tu aplicación.
Obtención dependiente
SWR le permite recuperar datos que dependen de otros datos. Eso significa que puede recuperar los datos A y, una vez realizada la operación, los utiliza para recuperar los datos B evitando cascadas. Y esta característica ayuda cuando tienes datos relacionales.
Dicho esto, SWR ayuda a incrementar la experiencia del usuario en cualquier asunto. Tiene más funciones que eso y, en muchos casos, es mejor usarlo en lugar de Fetch API o la biblioteca Axios.
Conclusión
A lo largo de este artículo, hemos visto por qué SWR es una biblioteca increíble. Permite la recuperación remota de datos utilizando React Hooks y ayuda a simplificar algunas funciones avanzadas listas para usar, como paginación, almacenamiento en caché de datos, recuperación en intervalos, recuperación de la posición de desplazamiento, etc. SWR también es independiente del backend, lo que significa que puede recuperar datos de cualquier tipo de API o base de datos. En definitiva, SWR aumenta mucho la experiencia de usuario de tus aplicaciones React, tiene un futuro brillante y debes vigilarlo o mejor usarlo en tu próxima aplicación React.
Puede obtener una vista previa del proyecto terminado en vivo aquí .
¡Gracias por leer!
Próximos pasos
Puede continuar consultando los siguientes enlaces que le brindarán una mejor comprensión más allá del alcance de este tutorial.
- ROE
- Documentos SWR
Lecturas adicionales sobre SmashingMag:
- Componentes de diseño en React
- Mejores reductores con Immer
- Componentes de orden superior en React
- Construyendo componentes de React reutilizables usando Tailwind
(ks, ra, yk, il)Explora más en
- Reaccionar
- Ganchos de reacción
- javascript
- Herramientas
Deja un comentario