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

Video
20 min~4 min lectura

Reproductor de 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.