Saltar al contenido

Lección 12 de 20 · Lectura y práctica

Manejo de datos asíncronos y estados de carga/error

Tipo de lección: VideoConcepto claveEn el desarrollo de aplicaciones móviles con React Native y Expo, el manejo de datos asíncronos es fundamental para crear experiencias de usuario fluidas. Imagina que estás pidiendo comida en.

Del concepto a la práctica

Taller de esta lección

Una pantalla asíncrona necesita estados mutuamente comprensibles: carga mientras espera, datos cuando termina bien y error cuando la operación no puede completarse. El estado de carga no debe borrar necesariamente datos anteriores si estás actualizando una lista existente.

Ejemplo resuelto

  1. Define loading, data y error con valores iniciales claros.

  2. Antes de pedir datos, activa loading y limpia el error anterior.

  3. En éxito, guarda la lista y desactiva loading.

  4. En fallo, conserva un mensaje accionable y ofrece reintento. Un error frecuente es dejar loading activo dentro de catch, bloqueando la interfaz. Corrígelo con una limpieza común en finally o con una transición equivalente.

Pruébalo

Simula una respuesta lenta de dos segundos y después una respuesta fallida; incluye un botón Reintentar.

Comprueba tu resultado

Durante la espera aparece Cargando; tras éxito aparecen los productos; tras fallo aparece el mensaje y el botón, y ninguna de las dos ramas deja la pantalla bloqueada.

Un resultado corresponde a una petición

Para dos segundos simulados usa un temporizador local, sin consultar una API externa. Al comenzar una carga, limpia error y declara si limpias data o conservas una lista marcada como anterior. En el contrato de este ejercicio se limpia data; carga→éxito muestra dos registros, carga→fallo muestra error y Reintentar. Un finally de una petición antigua no debe apagar el spinner de una nueva.

En un efecto, declara let vigente=true; después de cada await, antes de modificar data/error/loading, comprueba vigente; cleanup la cambia a false. Si permites reintentos en la misma ejecución, añade un número de petición y acepta solo el último. AbortController puede cancelar cuando el transporte lo soporta; ignorar una respuesta obsoleta evita publicar el resultado incluso si no pudo cancelarse. No conviertas directamente la función pasada a useEffect en async, porque debe devolver cleanup y no una promesa.

Fixture: petición A inicia para p1, B para p2; resuelve B primero y A después. La salida final debe seguir siendo p2 y loading=false. En fallo B debe quedar error de B, sin datos de A etiquetados como p2. Registra la secuencia de resolución de ese caso junto a los caminos success/failure; demostrar un spinner una vez no prueba la protección de carreras.

Estados de carga, éxito, vacío y error ofrecen salida mediante reintento.
CursaloMapa de práctica
Una petición tiene varios estados

Distingue carga, éxito con datos, respuesta vacía y error. Conserva una salida clara mediante reintento y evita mostrar una respuesta antigua como si correspondiera a la consulta vigente.

Ver la infografía en tamaño completo ↗

Tipo de lección: Video

Concepto clave

En el desarrollo de aplicaciones móviles con React Native y Expo, el manejo de datos asíncronos es fundamental para crear experiencias de usuario fluidas. Imagina que estás pidiendo comida en un restaurante: no te quedas congelado esperando tu pedido, sino que sigues con tu conversación mientras la cocina trabaja. De la misma forma, tu app debe seguir respondiendo mientras espera datos de una API.

Los estados de carga y error son como semáforos para tu interfaz: el estado de carga (loading) indica "espera, estamos trabajando", el estado de éxito muestra los datos obtenidos, y el estado de error alerta cuando algo falla. Sin estos estados, los usuarios verían pantallas vacías o congeladas, lo que genera frustración y abandono de la app.

Cómo funciona en la práctica

Para implementar esto en React Native, seguimos un patrón de tres estados: loading, success y error. Primero, definimos un estado inicial que controle qué mostrar. Luego, al iniciar una petición asíncrona (como un fetch a una API), cambiamos al estado de loading. Cuando la petición termina, actualizamos el estado con los datos o con el error correspondiente.

Paso a paso: 1) Crear estados para datos, loading y error. 2) Usar useEffect para disparar la petición al montar el componente. 3) En el renderizado, condicionar la UI según el estado actual. 4) Incluir manejo de errores con try/catch. Este flujo asegura que la app siempre muestre algo significativo al usuario.

Código en acción

Aquí tienes un ejemplo básico usando fetch y useState:

import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';

export default function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) throw new Error('Error en la petición');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, []);

  if (loading) return ;
  if (error) return Error: {error};
  return (
    
      Datos: {JSON.stringify(data)}
    
  );
}

Ahora, una mejora con refactorización usando un custom hook para reutilizar la lógica:

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        if (!response.ok) throw new Error('Error en la petición');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Errores comunes

  • No manejar estados intermedios: Olvidar el estado de loading hace que la app parezca congelada. Siempre incluye un indicador visual como ActivityIndicator.
  • Ignorar errores de red: Asumir que la API siempre responde es un error. Usa try/catch y verifica response.ok para capturar fallos.
  • Actualizar estado en componentes desmontados: Si un usuario navega rápido, puede causar memory leaks. Usa una bandera o abort controllers para cancelar peticiones.
  • No limpiar efectos: En useEffect, olvidar la función de cleanup puede llevar a comportamientos inesperados en peticiones repetidas.
  • UI bloqueante: Mostrar pantallas vacías durante la carga. Mejora la experiencia con skeletons o placeholders.

Checklist de dominio

  1. Sé implementar un estado triple (loading, success, error) en un componente React Native.
  2. Puedo usar fetch o axios para hacer peticiones asíncronas con manejo de errores.
  3. Conozco cómo usar useEffect para disparar peticiones al montar un componente.
  4. Sé crear custom hooks para reutilizar lógica de fetching en múltiples componentes.
  5. Puedo optimizar la experiencia de usuario con indicadores de carga y mensajes de error claros.
  6. Entiendo cómo evitar memory leaks cancelando peticiones en componentes desmontados.
  7. Sé refactorizar código para mejorar mantenibilidad y rendimiento.

Crear una app de clima con manejo de estados asíncronos

En este ejercicio, desarrollarás una aplicación móvil que muestra el clima actual usando una API pública. Sigue estos pasos:

  1. Crea un nuevo proyecto Expo con npx create-expo-app ClimaApp.
  2. Instala axios para peticiones HTTP con npm install axios.
  3. Diseña un componente principal que tenga: un campo de entrada para la ciudad, un botón para buscar, y áreas para mostrar temperatura, condiciones y un indicador de carga.
  4. Implementa los estados: loading (boolean), weatherData (objeto), y error (string).
  5. Usa la API de OpenWeatherMap (https://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}&units=metric) – registra una API_KEY gratuita.
  6. En el botón de buscar, dispara una petición asíncrona que actualice los estados según el resultado.
  7. Muestra un ActivityIndicator durante loading, los datos del clima en éxito, o un mensaje de error si falla.
  8. Agrega un manejo para cuando el usuario escriba una ciudad inválida o haya problemas de red.

Objetivo: Una app funcional que responda fluidamente a las interacciones del usuario.

Pistas
  • Usa useState y useEffect para gestionar los estados y efectos secundarios.
  • Recuerda que axios devuelve una promesa, maneja los errores con .catch o try/catch.
  • Prueba con ciudades como 'Madrid' o 'Londres' para verificar la API.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con React Native con Expo: Desarrollo de Apps Nativas para iOS y Android

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.