Ejemplo de React consumiendo API de productos (versión mock y real)
Ejemplo de React consumiendo API de productos (versión mock y real)
Aquí te presento un componente React que muestra productos en cards de Bootstrap, con dos versiones: una usando datos mockeados y otra consumiendo un endpoint real.
Versión completa con ambas implementaciones
import React, { useState, useEffect } from 'react';
import { Card, Container, Row, Col, Spinner } from 'react-bootstrap';
const ProductosApp = () => {
const [modo, setModo] = useState('mock'); // 'mock' o 'api'
const [productos, setProductos] = useState([]);
const [cargando, setCargando] = useState(false);
const [error, setError] = useState(null);
// Datos mockeados
const datosMock = [
{ articulo: 'P001', descripcion: 'Laptop HP EliteBook', precio: 1250.99 },
{ articulo: 'P002', descripcion: 'Teclado mecánico RGB', precio: 89.50 },
{ articulo: 'P003', descripcion: 'Mouse inalámbrico', precio: 35.20 },
{ articulo: 'P004', descripcion: 'Monitor 24" Full HD', precio: 199.99 },
];
// Función para cargar productos mockeados
const cargarMock = () => {
setCargando(true);
setTimeout(() => {
setProductos(datosMock);
setCargando(false);
}, 1000); // Simulamos delay de red
};
// Función para cargar productos desde API real
const cargarDesdeAPI = async () => {
setCargando(true);
setError(null);
try {
const response = await fetch('https://api.ejemplo.com/productos');
if (!response.ok) {
throw new Error('Error al obtener productos');
}
const data = await response.json();
setProductos(data);
} catch (err) {
setError(err.message);
console.error('Error:', err);
} finally {
setCargando(false);
}
};
useEffect(() => {
if (modo === 'mock') {
cargarMock();
} else {
cargarDesdeAPI();
}
}, [modo]);
return (
<Container className="mt-5">
<h1 className="mb-4">Catálogo de Productos</h1>
<div className="mb-4">
<button
className={`btn ${modo === 'mock' ? 'btn-primary' : 'btn-outline-primary'} me-2`}
onClick={() => setModo('mock')}
>
Versión Mock
</button>
<button
className={`btn ${modo === 'api' ? 'btn-primary' : 'btn-outline-primary'}`}
onClick={() => setModo('api')}
>
Versión API Real
</button>
</div>
{error && (
<div className="alert alert-danger">
Error: {error}. {modo === 'api' && '¿Estás seguro que la API está disponible?'}
</div>
)}
{cargando ? (
<div className="text-center">
<Spinner animation="border" role="status">
<span className="visually-hidden">Cargando...</span>
</Spinner>
<p>Cargando productos...</p>
</div>
) : (
<Row xs={1} md={2} lg={3} className="g-4">
{productos.map((producto) => (
<Col key={producto.articulo}>
<Card className="h-100">
<Card.Body>
<Card.Title>{producto.articulo}</Card.Title>
<Card.Subtitle className="mb-2 text-muted">
${producto.precio.toFixed(2)}
</Card.Subtitle>
<Card.Text>{producto.descripcion}</Card.Text>
</Card.Body>
<Card.Footer>
<button className="btn btn-sm btn-outline-success">
Agregar al carrito
</button>
</Card.Footer>
</Card>
</Col>
))}
</Row>
)}
</Container>
);
};
export default ProductosApp;Versión solo con datos mockeados (simplificada)
import React from 'react';
import { Card, Container, Row, Col } from 'react-bootstrap';
const ProductosMock = () => {
const productos = [
{ articulo: 'P001', descripcion: 'Laptop HP EliteBook', precio: 1250.99 },
{ articulo: 'P002', descripcion: 'Teclado mecánico RGB', precio: 89.50 },
{ articulo: 'P003', descripcion: 'Mouse inalámbrico', precio: 35.20 },
{ articulo: 'P004', descripcion: 'Monitor 24" Full HD', precio: 199.99 },
];
return (
<Container className="mt-5">
<h1 className="mb-4">Productos (Datos Mock)</h1>
<Row xs={1} md={2} lg={3} className="g-4">
{productos.map((producto) => (
<Col key={producto.articulo}>
<Card className="h-100">
<Card.Body>
<Card.Title>{producto.articulo}</Card.Title>
<Card.Subtitle className="mb-2 text-muted">
${producto.precio.toFixed(2)}
</Card.Subtitle>
<Card.Text>{producto.descripcion}</Card.Text>
</Card.Body>
<Card.Footer>
<button className="btn btn-sm btn-outline-success">
Agregar al carrito
</button>
</Card.Footer>
</Card>
</Col>
))}
</Row>
</Container>
);
};
export default ProductosMock;Versión solo con API real (simplificada)
import React, { useState, useEffect } from 'react';
import { Card, Container, Row, Col, Spinner } from 'react-bootstrap';
const ProductosAPI = () => {
const [productos, setProductos] = useState([]);
const [cargando, setCargando] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchProductos = async () => {
try {
const response = await fetch('https://api.ejemplo.com/productos');
if (!response.ok) {
throw new Error('Error al obtener productos');
}
const data = await response.json();
setProductos(data);
} catch (err) {
setError(err.message);
console.error('Error:', err);
} finally {
setCargando(false);
}
};
fetchProductos();
}, []);
if (cargando) {
return (
<Container className="mt-5 text-center">
<Spinner animation="border" role="status">
<span className="visually-hidden">Cargando...</span>
</Spinner>
<p>Cargando productos...</p>
</Container>
);
}
if (error) {
return (
<Container className="mt-5">
<div className="alert alert-danger">
Error: {error}. ¿Estás seguro que la API está disponible?
</div>
</Container>
);
}
return (
<Container className="mt-5">
<h1 className="mb-4">Productos (API Real)</h1>
<Row xs={1} md={2} lg={3} className="g-4">
{productos.map((producto) => (
<Col key={producto.articulo}>
<Card className="h-100">
<Card.Body>
<Card.Title>{producto.articulo}</Card.Title>
<Card.Subtitle className="mb-2 text-muted">
${producto.precio.toFixed(2)}
</Card.Subtitle>
<Card.Text>{producto.descripcion}</Card.Text>
</Card.Body>
<Card.Footer>
<button className="btn btn-sm btn-outline-success">
Agregar al carrito
</button>
</Card.Footer>
</Card>
</Col>
))}
</Row>
</Container>
);
};
export default ProductosAPI;Características destacadas:
Versión mock:
No requiere backend
Datos estáticos para desarrollo rápido
Útil para pruebas y prototipos
Versión API real:
Manejo de estados de carga
Manejo de errores
Uso de useEffect para el fetch de datos
Estructura async/await moderna
UI consistente:
Cards responsive con Bootstrap
Formato de precio consistente
Diseño limpio y profesional
Para usar estos componentes, necesitarás instalar las dependencias de Bootstrap:
npm install react-bootstrap bootstrap
Comentarios
Publicar un comentario