Inicio / Artículos / Cómo React Query redujo 500 líneas en la capa de API de una aplicación React Native

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.

1364 palabras

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
  • Lógica de actualización al tirar hacia arriba
  • Su propio método de caché
  • Desencadenadores manuales de nueva carga
  • 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