Concepto clave
La integración con APIs de productos y el manejo de autenticación son dos pilares fundamentales en cualquier aplicación de e-commerce móvil. Imagina que tu app es una tienda física: la API de productos es el inventario almacenado en la bodega, mientras que la autenticación es el sistema de seguridad que verifica quién puede entrar y qué puede comprar. Sin una conexión eficiente al inventario, los clientes no verán productos disponibles; sin autenticación robusta, cualquiera podría acceder a datos sensibles o realizar compras no autorizadas.
En React Native con Expo, trabajamos con APIs RESTful que devuelven datos en formato JSON. Para productos, típicamente consumimos endpoints como /api/products o /api/products/:id. La autenticación suele implementarse con tokens JWT (JSON Web Tokens), donde el usuario inicia sesión, recibe un token, y ese token se incluye en los headers de las peticiones subsiguientes para verificar su identidad. Es crucial entender que estas operaciones son asíncronas: tu app debe manejar estados de carga, éxito y error mientras espera respuestas del servidor.
Cómo funciona en la práctica
Vamos a construir un flujo típico para nuestra app de e-commerce. Primero, configuramos la autenticación: al iniciar sesión, enviamos credenciales al endpoint de login, recibimos un token JWT, y lo almacenamos de forma segura usando AsyncStorage o SecureStore en Expo. Luego, para acceder a los productos, hacemos peticiones GET al endpoint de productos, incluyendo el token en el header Authorization. Este proceso se divide en pasos claros:
- Configurar el cliente HTTP (usando fetch o axios) con interceptores para manejar tokens.
- Implementar un contexto de autenticación en React para compartir el estado del usuario en toda la app.
- Crear hooks personalizados como useProducts() para centralizar la lógica de fetching de datos.
- Manejar errores de red y respuestas no exitosas con try-catch y estados de error.
Código en acción
Aquí tienes un ejemplo funcional de un servicio de autenticación y fetching de productos. Empezamos con la configuración básica usando axios:
// services/api.js
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
const API_URL = 'https://api.tuecommerce.com';
const api = axios.create({
baseURL: API_URL,
timeout: 10000,
});
// Interceptor para agregar token a las peticiones
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('userToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export const login = async (email, password) => {
try {
const response = await api.post('/auth/login', { email, password });
await AsyncStorage.setItem('userToken', response.data.token);
return response.data.user;
} catch (error) {
throw new Error('Error en login: ' + error.message);
}
};
export const fetchProducts = async (page = 1, limit = 10) => {
try {
const response = await api.get(`/products?page=${page}&limit=${limit}`);
return response.data;
} catch (error) {
throw new Error('Error fetching products: ' + error.message);
}
};
Ahora, veamos cómo usar este servicio en un componente de lista de productos, mostrando el antes y después de manejar estados:
// Antes: Sin manejo de estados, propenso a errores
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import { fetchProducts } from '../services/api';
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
fetchProducts().then(data => setProducts(data));
}, []);
return (
{products.map(product => (
{product.name}
))}
);
};
// Después: Con manejo de estados (loading, error, data)
const ProductListImproved = () => {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const loadProducts = async () => {
try {
setLoading(true);
const data = await fetchProducts();
setProducts(data);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
loadProducts();
}, []);
if (loading) return Cargando productos...;
if (error) return Error: {error};
return (
{products.map(product => (
{product.name} - ${product.price}
))}
);
};
Errores comunes
- No manejar estados de carga y error: Como vimos en el ejemplo anterior, sin esto, la app puede quedar congelada o mostrar interfaces rotas. Siempre implementa estados para loading, data y error.
- Almacenar tokens de forma insegura: Usar AsyncStorage sin cifrado para tokens JWT expone datos sensibles. En Expo, prefiere SecureStore para tokens, ya que usa el keychain de iOS y Keystore de Android.
- No validar respuestas de API: Asumir que todas las respuestas son exitosas lleva a crashes. Verifica status codes y maneja casos como 401 (no autorizado) para redirigir al login.
- Hacer fetching excesivo de datos: Solicitar todos los productos de una vez puede ralentizar la app. Implementa paginación o lazy loading, como se muestra en fetchProducts con parámetros page y limit.
- Olvidar limpiar suscripciones o timeouts: En useEffect, si usas suscripciones, asegúrate de retornar una función de cleanup para evitar memory leaks.
Checklist de dominio
- Configurar un cliente HTTP (axios o fetch) con manejo de headers para autenticación.
- Implementar login/logout con almacenamiento seguro de tokens JWT usando SecureStore de Expo.
- Crear hooks o servicios reutilizables para fetching de productos con paginación.
- Manejar estados de carga, éxito y error en componentes al consumir APIs.
- Probar la app sin conexión a internet para verificar manejo de errores de red.
- Proteger rutas o pantallas basado en el estado de autenticación (ej: solo usuarios logueados ven el carrito).
- Optimizar rendimiento con técnicas como memoización de peticiones o uso de React Query si es necesario.
Implementar autenticación y lista de productos en una app de e-commerce
En este ejercicio, crearás una pantalla de login y una lista de productos integradas con una API real. Sigue estos pasos:
- Configura un nuevo proyecto Expo con
npx create-expo-app ecommerce-appy añade las dependencias: axios, @react-native-async-storage/async-storage, y expo-secure-store. - Crea un archivo
services/api.jsbasado en el ejemplo de código proporcionado. Usa la API de prueba JSONPlaceholder para productos (https://jsonplaceholder.typicode.com/posts) y simula login con un endpoint mock (ej: POST a https://reqres.in/api/login con email: '[email protected]', password: 'cityslicka'). - Implementa un contexto de autenticación usando React Context que gestione el estado del usuario y el token. Incluye funciones para login, logout, y verificar autenticación.
- Crea una pantalla de login con dos TextInputs para email y password, y un botón que llame a la función de login. Al éxito, navega a la pantalla de productos.
- Desarrolla una pantalla de productos que use el hook useProducts (creado por ti) para fetch de datos con paginación. Muestra al menos 10 productos con nombre y precio, e incluye un indicador de carga y manejo de errores.
- Protege la pantalla de productos para que solo sea accesible si el usuario está autenticado, redirigiendo al login si no.
- Prueba la app en un emulador o dispositivo, verificando que el login persiste al recargar y que los productos se cargan correctamente.
- Usa SecureStore de Expo para almacenar el token JWT de forma segura en lugar de AsyncStorage para datos sensibles.
- En la paginación, implementa un botón 'Cargar más' que incremente el parámetro page en fetchProducts.
- Para simular errores, desconecta temporalmente internet o usa URLs incorrectas en la API y verifica que tu app muestre mensajes amigables.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.