Integración con API de productos y manejo de autenticación

Lectura
30 min~6 min lectura

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:

  1. Configurar el cliente HTTP (usando fetch o axios) con interceptores para manejar tokens.
  2. Implementar un contexto de autenticación en React para compartir el estado del usuario en toda la app.
  3. Crear hooks personalizados como useProducts() para centralizar la lógica de fetching de datos.
  4. 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

  1. Configurar un cliente HTTP (axios o fetch) con manejo de headers para autenticación.
  2. Implementar login/logout con almacenamiento seguro de tokens JWT usando SecureStore de Expo.
  3. Crear hooks o servicios reutilizables para fetching de productos con paginación.
  4. Manejar estados de carga, éxito y error en componentes al consumir APIs.
  5. Probar la app sin conexión a internet para verificar manejo de errores de red.
  6. Proteger rutas o pantallas basado en el estado de autenticación (ej: solo usuarios logueados ven el carrito).
  7. 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:

  1. Configura un nuevo proyecto Expo con npx create-expo-app ecommerce-app y añade las dependencias: axios, @react-native-async-storage/async-storage, y expo-secure-store.
  2. Crea un archivo services/api.js basado 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').
  3. 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.
  4. 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.
  5. 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.
  6. Protege la pantalla de productos para que solo sea accesible si el usuario está autenticado, redirigiendo al login si no.
  7. Prueba la app en un emulador o dispositivo, verificando que el login persiste al recargar y que los productos se cargan correctamente.
Pistas
  • 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.