Concepto clave
En el desarrollo de aplicaciones móviles con React Native y Expo, la gestión de estado dinámico es fundamental para crear interfaces de usuario que respondan a datos cambiantes en tiempo real. Imagina una aplicación de clima: la temperatura, condiciones atmosféricas y pronósticos no son estáticos; se actualizan constantemente. El estado dinámico permite que tu app refleje estos cambios sin necesidad de recargar manualmente, similar a cómo un termómetro digital ajusta su lectura cuando la temperatura ambiente varía.
En React Native, el estado se maneja típicamente con useState y useEffect de React, o con librerías como Context API o Redux para casos más complejos. Para una app de clima, el estado dinámico incluye no solo los datos meteorológicos actuales, sino también el estado de carga, errores de red y preferencias del usuario. Esto crea una experiencia fluida donde la interfaz se adapta automáticamente a nuevas informaciones, manteniendo al usuario informado sin interrupciones.
Cómo funciona en la práctica
Vamos a construir una app de clima paso a paso. Primero, configura un proyecto en Expo usando npx create-expo-app WeatherApp. Luego, instala dependencias esenciales: expo-location para obtener la ubicación del usuario y axios para hacer peticiones a una API de clima como OpenWeatherMap. En la práctica, el flujo es: 1) Obtener permisos de ubicación, 2) Hacer una solicitud HTTP a la API con las coordenadas, 3) Actualizar el estado con la respuesta, y 4) Renderizar los datos en la UI.
Un ejemplo básico: al iniciar la app, se muestra un indicador de carga mientras se obtiene la ubicación. Una vez que la API responde, el estado cambia de loading a loaded, y la temperatura, icono y descripción se muestran en pantalla. Si hay un error (por ejemplo, sin conexión a internet), el estado cambia a error y se muestra un mensaje amigable. Este ciclo de estado—carga, éxito, error—es común en apps con datos dinámicos y asegura una experiencia robusta.
Código en acción
Aquí tienes un ejemplo funcional de un componente de clima usando useState y useEffect. Este código es copiable y ejecutable en un proyecto Expo:
import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import * as Location from 'expo-location';
import axios from 'axios';
const WeatherApp = () => {
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchWeather = async () => {
try {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setError('Permiso de ubicación denegado');
setLoading(false);
return;
}
let location = await Location.getCurrentPositionAsync({});
const { latitude, longitude } = location.coords;
const response = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=TU_API_KEY&units=metric`
);
setWeather(response.data);
setLoading(false);
} catch (err) {
setError('Error al obtener el clima');
setLoading(false);
}
};
fetchWeather();
}, []);
if (loading) {
return (
Cargando clima...
);
}
if (error) {
return (
{error}
);
}
return (
{weather.main.temp}°C
{weather.weather[0].description}
);
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
temp: { fontSize: 48, fontWeight: 'bold' },
error: { color: 'red' }
});
export default WeatherApp;Para mejorar este código, podríamos refactorizarlo usando Context API para manejar el estado globalmente, especialmente si añadimos más características como pronósticos futuros. Aquí el antes y después:
Antes: Estado local en el componente, difícil de compartir con otros componentes.
Después: Crear un contexto WeatherContext que proporcione el estado a toda la app, facilitando el acceso desde múltiples pantallas.
// WeatherContext.js
import React, { createContext, useState, useContext } from 'react';
const WeatherContext = createContext();
export const WeatherProvider = ({ children }) => {
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
return (
{children}
);
};
export const useWeather = () => useContext(WeatherContext);Errores comunes
- No manejar estados de carga y error: Muchos desarrolladores olvidan incluir indicadores de carga o mensajes de error, lo que resulta en una UI bloqueada o confusa. Siempre define estados para loading, data y error.
- Actualizar estado en loops o condiciones incorrectas: Evita llamar setState dentro de bucles sin control, ya que puede causar renders infinitos. Usa useEffect con dependencias claras.
- No limpiar suscripciones o efectos: En componentes con timers o listeners, olvidar la función de cleanup en useEffect puede llevar a fugas de memoria. Siempre retorna una función de limpieza si es necesario.
- Usar estado local para datos globales: Para datos compartidos entre múltiples componentes, el estado local puede volverse engorroso. Considera Context API o Redux en su lugar.
- Ignorar la optimización de rendimiento: Actualizar estado con objetos grandes o frecuentemente puede ralentizar la app. Usa useMemo o useCallback para optimizar cuando sea necesario.
Checklist de dominio
- Puedo configurar un proyecto Expo e instalar dependencias para una app de clima.
- Sé usar useState y useEffect para manejar estado dinámico con datos de API.
- Puedo implementar estados de carga, éxito y error en la UI.
- Entiendo cuándo refactorizar estado local a Context API para compartir datos.
- Sé evitar errores comunes como fugas de memoria o renders infinitos.
- Puedo integrar permisos de ubicación y hacer peticiones HTTP seguras.
- Soy capaz de probar la app en dispositivos iOS y Android usando Expo Go.
Construye una app de clima con pronóstico extendido
Sigue estos pasos para crear una app de clima que muestre el clima actual y un pronóstico de 5 días, aplicando gestión de estado dinámico en React Native con Expo:
- Configura el proyecto: Crea una nueva app Expo llamada
WeatherForecastAppy instalaexpo-location,axiosy@react-navigation/nativepara navegación. - Implementa el estado: En un componente principal, usa useState para manejar: clima actual, pronóstico de 5 días, estado de carga y errores. Inicializa los estados apropiadamente.
- Obtén datos de la API: En useEffect, solicita permisos de ubicación y haz dos peticiones a OpenWeatherMap: una para el clima actual y otra para el pronóstico (endpoint
/forecast). Actualiza el estado con las respuestas. - Diseña la UI: Crea dos pantallas: una para el clima actual (temperatura, icono, descripción) y otra para el pronóstico (lista de días con temperaturas). Usa React Navigation para cambiar entre ellas.
- Maneja errores y carga: Muestra un ActivityIndicator durante la carga y un mensaje de error si falla la API o los permisos. Asegúrate de que la UI responda a cambios de estado.
- Refactoriza con Context API: Si el estado se vuelve complejo, mueve la lógica a un WeatherContext para compartir datos entre pantallas sin prop drilling.
- Prueba la app: Ejecuta en un emulador o dispositivo físico usando Expo Go, verifica que los datos se actualicen dinámicamente y la navegación funcione.
- Usa la API de OpenWeatherMap: necesitarás una clave gratuita de su sitio web para hacer peticiones.
- Para el pronóstico de 5 días, el endpoint /forecast devuelve datos en intervalos de 3 horas; agrupa por día para simplificar.
- Considera usar FlatList para mostrar el pronóstico, ya que maneja listas largas eficientemente en React Native.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.