Cómo React Query redujo 500 líneas en la capa de API de una aplicación React Native
Un estudio de caso real en React Native que muestra cómo pasar de la obtención manual de datos con useEffect a React Query eliminó el código repetitivo y mejoró el caché y la gestión fuera de línea.
Introducción
Hace algún tiempo, un códigobase de React Native que quizás reconozca se enfrentó a un problema familiar.
Casi todas las pantallas que necesitaban datos remotos seguían el mismo patrón:
- Llamadas para obtener datos dentro de
useEffect - Varias banderas de carga separadas
- Bloques personalizados para manejar errores
- Lógica de actualización al arrastrar hecha a mano
- Mecanismos manuales de intento repetido
- Soluciones temporales para el caché local
Desde el punto de vista funcional, nada de esto estaba roto. Pero mantener la consistencia en decenas de pantallas se convirtió en una verdadera carga de mantenimiento.
Al pasar a React Query (de TanStack), el equipo logró eliminar una gran cantidad de código de red repetitivo, obteniendo a cambio un mejor caché, una gestión más eficiente de la carga y un comportamiento offline más fiable. La biblioteca incluye caché integrado para consultas, actualización automática en segundo plano y lógica sensible a la red, lo que reduce en gran medida la necesidad de escribir manualmente esa maquinaria de estado.
A continuación se presenta una comparación lado a lado del antiguo enfoque manual con la versión de React Query, utilizando patrones extraídos de pantallas reales de React Native en entornos de producción.
El problema con la gestión tradicional de APIs
La configuración típica de una pantalla era más o menos así:
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
try {
setLoading(true);
const response = await api.getPosts();
setData(response);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
Ese mismo código genérico aparecía una y otra vez en toda la aplicación.
Cada pantalla necesitaba gestionar de forma independiente:
- Una bandera de carga
- Una bandera de error
- El manejo de intentos de reintentar
A medida que la aplicación crecía, este patrón repetitivo se volvía cada vez más difícil de mantener consistente.
Llega React Query
Esa misma pantalla, reescrita con React Query, se redujo a lo siguiente:
const { data, isLoading, error, refetch } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
});
Esa es toda la implementación.
React Query se encarga automáticamente de todo lo siguiente:
- Indicadores de carga
- Estados de error
- Deduplicación de solicitudes idénticas en proceso
- Nueva carga de datos en segundo plano
- Gestión del caché
- Vuelta a intentar solicitudes fallidas
- Reacción ante la reconexión de red
La mayor parte de este comportamiento está disponible de forma gratuita desde el inicio, y se puede ajustar mediante opciones como staleTime, gcTime, configuración de intentos repetidos y ajustes de nueva carga.
Comparación #1: Solicitudes de red
Antes de React Query
Imagínese tres pantallas separadas que todas necesitan los mismos datos del perfil de usuario.
Sin ninguna capa de caché compartida, cada una envía su propia solicitud:
Profile Screen → API Call
Settings Screen → API Call
Dashboard Screen → API Call
El resultado: tres llamadas a la red separadas para los mismos datos.
Con React Query
Profile Screen → API Call
Settings Screen → Cached Data
Dashboard Screen → Cached Data
El resultado esta vez: solo una llamada a la red.
React Query almacena los resultados bajo una clave de consulta y comparte esos datos en caché entre todos los componentes que los solicitan. Cualquier pantalla que solicite la misma clave posteriormente obtiene el valor en caché al instante, mientras que una actualización en segundo plano puede mantenerlo actualizado de forma silenciosa.
Resultado en producción
En las pantallas que los usuarios visitan con frecuencia, esto se traduce en:
- Mucho menos número de solicitudes duplicadas a la API
- Menor carga en los servidores backend
- Transiciones más rápidas entre pantallas
Comparación #2: Eficiencia del caché
Se podría decir que el caché es donde React Query aporta más valor.
Cuando se vuelve a solicitar la misma consulta antes de que su copia en caché se vuelva obsoleta:
useQuery({
queryKey: ["products"],
queryFn: getProducts,
staleTime: 300000,
});
La interfaz puede mostrar los datos en caché de inmediato, con React Query actualizándolos silenciosamente en segundo plano si es necesario. Las entradas en caché se mantienen y, eventualmente, se eliminan según la configuración que usted defina.
Ejemplo real
Considere la pantalla de lista de productos de una aplicación de comercio electrónico.
Sin caché, al abrir la pantalla significa:
Open Products
↓
Network Request
↓
Navigate Back
↓
Open Products Again
↓
Network Request
Con React Query en uso, el mismo flujo se convierte en:
Open Products
↓
Network Request
↓
Navigate Back
↓
Open Products Again
↓
Instant Cached Data
La diferencia es que la aplicación parece notablemente más rápida para quien la utiliza.
Comparación #3: Estados de carga
Antes de adoptar React Query, rastrear los estados de carga implicaba manejar varios valores booleanos:
const [loading, setLoading] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [isRetrying, setIsRetrying] = useState(false);
Más tarde, una sola llamada al hook expone todo lo necesario:
const {
isLoading,
isFetching,
isRefetching,
} = useQuery(...)
React Query distingue entre la primera carga y cualquier solicitud en segundo plano posterior, lo que hace que la lógica de interfaz gráfica relacionada sea mucho más sencilla de comprender.
Beneficio real
En lugar de mostrar un spinner de pantalla completa en cada solicitud, la aplicación puede diferenciar:
- Carga inicial: cargador de pantalla completa
- Actualización en segundo plano: un spinner pequeño y discreto
- Datos ya almacenados en caché: sin interrupción visible alguna
El resultado resulta considerablemente más ágil para quien utilice la aplicación.
Comparación n.º 4: Soporte sin conexión
El comportamiento en modo sin conexión es una de esas cosas que los equipos tienden a subestimar.
Manejarlo manualmente suele verse así:
Check Connectivity
Pause Requests
Retry Later
Handle Errors
Refetch On Reconnect
Eso significa que hay lógica de conectividad personalizada dispersa por todo el código.
React Query, en cambio, ofrece una gestión integrada tanto en línea como sin conexión, además de la posibilidad de volver a cargar datos en respuesta a eventos de reconexión. Dentro de React Native, se puede implementar esto utilizando onlineManager junto con los detectores de estado de red de la plataforma.
Por ejemplo:
onlineManager.setEventListener(...)
React Query también se puede configurar para funcionar en modo prioridad sin conexión, ajustando su comportamiento de red en consecuencia.
Ejemplo real
Tomemos como ejemplo una aplicación para leer noticias.
A lo largo del día, la conexión del usuario podría ser la siguiente:
- Mañana: en línea
- Tarde: sin conexión
- Noche: de nuevo en línea
Durante toda esta secuencia, los artículos almacenados previamente en caché siguen siendo accesibles, y una vez restablecida la conexión, el contenido actualizado se puede sincronizar automáticamente.
Casos de uso en el mundo real
1. Aplicaciones de noticias
Lo que esto aporta:
- Artículos en caché
- Actualización automática en segundo plano
- Menor tráfico general de la API
- La posibilidad de seguir leyendo sin conexión
2. Aplicaciones de comercio electrónico
Lo que esto aporta:
- Listados de productos en caché
- Precarga anticipada de categorías
- Navegación más rápida entre secciones
- Una experiencia de compra notablemente más fluida
React Query también permite precargar datos antes incluso de que ocurra la navegación, reduciendo los tiempos de espera percibidos.
3. Aplicaciones de panel de control
Lo que esto aporta:
- Widgets que se actualizan automáticamente
- Un caché compartido entre varias pantallas
- Menos actividad de red
- Gestión de estado mucho más sencilla en general
Este patrón se adapta especialmente bien a los paneles de análisis y a los paneles administrativos.
Qué eliminamos realmente
Una vez finalizada la migración:
Eliminado
- Gestión personalizada del estado de carga
- Código manual para intentos repetidos
- Llamadas duplicadas a la API
- Código genérico para actualización al arrastrar
- Lógica de caché desarrollada internamente
- Gestión manual de recarga
Añadido
- La biblioteca React Query en sí
- Claves de consulta
- Una instancia de
QueryClient
El efecto neto: ya no se necesitaban aproximadamente 500 líneas de código para manejar la API.
Cuando React Query podría no ser necesario
Podría ser un exceso recurrir a React Query si:
- La aplicación realiza solo unas pocas llamadas a la API
- Los datos subyacentes cambian muy poco
- Realmente no se necesita caché
- El comportamiento sin conexión no es importante para el caso de uso
No obstante, en la mayoría de las aplicaciones de producción, los beneficios suelen superar rápidamente la curva de aprendizaje inicial.
Consideraciones finales
React Query es algo más que otra forma de obtener datos.
Funciona como una solución completa para la gestión del estado del servidor, eliminando el código API repetitivo y mejorando al mismo tiempo el caché, el comportamiento de carga, la eficiencia de red y la experiencia fuera de línea.
La mayor ventaja aquí no fue el rendimiento bruto.
Fue la reducción de la complejidad.
Esa combinación es lo que hizo que la migración valiera la pena.
Lecturas relacionadas
- Dónde se esconde la latencia de React Native: los cruces de límites y no el código lento — Aprenda por qué las APIs rápidas y los componentes memorizados aún pueden parecer lentos en React Native, y cómo el agrupamiento de solicitudes, la limitación del tráfico y el diseño de la era JSI reducen los costos entre entornos de ejecución.
- De Bridge a JSI: decidir cuándo migrar a la nueva arquitectura de React Native — Cómo JSI, Fabric y TurboModules reemplazan al antiguo bridge de React Native, qué significan en la práctica las mejoras reportadas, y cómo auditar y migrar una aplicación existente de forma segura.