App React que consume tu API de Pasteles
App React que consume tu API de Pasteles 馃嵃
Vamos a crear una aplicaci贸n en React con Vite (la forma moderna y recomendada) que consuma tu endpoint http://localhost:8000/api/pasteles.
馃搵 Requisitos previos
Antes de empezar, aseg煤rate de tener instalado:
| Herramienta | Verificar con | Versi贸n m铆nima |
|---|---|---|
| Node.js | node -v | v18+ |
| npm | npm -v | v9+ |
| Laravel corriendo | php artisan serve | — |
Si no tienes Node.js, desc谩rgalo de nodejs.org.
Importante: Deja Laravel corriendo en otra terminal:
php artisan serveDebe estar disponible en http://localhost:8000.
1️⃣ Crear el proyecto React con Vite
En una terminal nueva (distinta a la de Laravel), ve a la carpeta donde quieras tu proyecto y ejecuta:
npm create vite@latest pasteles-app -- --template reactFlujo completo
npm create vite@latest pasteles-app -- --template react
│ │ │ │ │
│ │ │ │ └─ opci贸n para create-vite
│ │ │ └──── separador: "lo de abajo es para el comando, no para npm"
│ │ └─────────────── nombre de la carpeta del proyecto
│ └──────────────────────────────── paquete generador (create-vite)
└────────────────────────────────────────── comando npmEquivalencia sin el --
En muchos casos podr铆as escribir directamente:
npx create-vite@latest pasteles-app --template reactAqu铆 no necesitas el -- porque ya est谩s ejecutando create-vite directamente, no a trav茅s de npm. El -- es necesario solo cuando pasas flags a trav茅s de npm create.
--template react
Es una bandera (flag) que pertenece a
create-vite, no a npm.Le dice a Vite: "genera el proyecto usando la plantilla de React" (en lugar de vanilla, vue, svelte, etc.).
Internamente Vite tiene plantillas predefinidas:
vanilla,vue,react,react-ts,svelte,solid, etc.
Esto te preguntar谩 algunas cosas. Si te pregunta por instalar create-vite, responde y.
Luego entra a la carpeta e instala dependencias:
cd pasteles-app
npm install¿Por qu茅 Vite y no Create React App?
Create React App (npx create-react-app) est谩 oficialmente deprecado desde 2023. Vite es m谩s r谩pido, moderno y es lo que recomienda la comunidad actualmente.
2️⃣ Instalar Axios (para consumir la API)
Axios es la librer铆a est谩ndar para hacer peticiones HTTP. Desde la ra铆z del proyecto:
npm install axiosAlternativa: puedes usar
fetch()nativo sin instalar nada, pero Axios es m谩s c贸modo.
3️⃣ Estructura del proyecto
Tu proyecto debe verse as铆:
pasteles-app/
├── src/
│ ├── App.jsx ← Componente principal (lo editaremos)
│ ├── App.css ← Estilos (lo editaremos)
│ ├── main.jsx ← Punto de entrada (no lo tocamos)
│ ├── index.css ← Estilos globales (lo editaremos)
│ └── services/
│ └── pastelService.js ← NUEVO: centraliza las llamadas a la API
├── index.html
└── package.json4️⃣ Crear el servicio de API
Crea la carpeta src/services/ y dentro el archivo pastelService.js:
// src/services/pastelService.js
import axios from 'axios';
// URL base de tu API Laravel
const API_URL = 'http://localhost:8000/api';
const api = axios.create({
baseURL: API_URL,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
});
// GET /api/pasteles - Obtener todos los pasteles
export const getPasteles = async () => {
const response = await api.get('/pasteles');
return response.data; // { success: true, data: [...], message: "..." }
};
// GET /api/pasteles/:id - Obtener uno
export const getPastel = async (id) => {
const response = await api.get(`/pasteles/${id}`);
return response.data;
};
// POST /api/pasteles - Crear
export const createPastel = async (pastel) => {
const response = await api.post('/pasteles', pastel);
return response.data;
};
// PUT /api/pasteles/:id - Actualizar
export const updatePastel = async (id, pastel) => {
const response = await api.put(`/pasteles/${id}`, pastel);
return response.data;
};
// DELETE /api/pasteles/:id - Eliminar
export const deletePastel = async (id) => {
const response = await api.delete(`/pasteles/${id}`);
return response.data;
};
export default api;馃挕 Centralizar las llamadas en un servicio es una buena pr谩ctica. Si ma帽ana cambia la URL o el endpoint, solo editas este archivo.
5️⃣ Crear el componente ListaPasteles
Crea src/components/ListaPasteles.jsx:
// src/components/ListaPasteles.jsx
import { useEffect, useState } from 'react';
import { getPasteles } from '../services/pastelService';
import PastelCard from './PastelCard';
function ListaPasteles() {
const [pasteles, setPasteles] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
cargarPasteles();
}, []);
const cargarPasteles = async () => {
try {
setLoading(true);
const respuesta = await getPasteles();
if (respuesta.success) {
setPasteles(respuesta.data);
} else {
setError('La API respondi贸 pero sin datos.');
}
} catch (err) {
console.error(err);
setError('No se pudo conectar con la API. ¿Est谩 corriendo Laravel?');
} finally {
setLoading(false);
}
};
if (loading) return <p className="estado">⏳ Cargando pasteles...</p>;
if (error) return <p className="estado error">❌ {error}</p>;
return (
<div>
<h1>馃嵃 Cat谩logo de Pasteles</h1>
<p className="contador">Total: {pasteles.length} pasteles</p>
<div className="grid-pasteles">
{pasteles.map((pastel) => (
<PastelCard key={pastel.id} pastel={pastel} />
))}
</div>
</div>
);
}
export default ListaPasteles;6️⃣ Crear el componente PastelCard
Crea src/components/PastelCard.jsx:
// src/components/PastelCard.jsx
function PastelCard({ pastel }) {
const disponible = pastel.disponible === 1;
return (
<div className="pastel-card">
<h3>{pastel.nombre}</h3>
<span className="sabor">Sabor: {pastel.sabor}</span>
<p className="precio">
${parseFloat(pastel.precio).toFixed(2)} MXN
</p>
<p className="descripcion">{pastel.descripcion}</p>
<span className={disponible ? 'badge disponible' : 'badge agotado'}>
{disponible ? '✅ Disponible' : '❌ Agotado'}
</span>
</div>
);
}
export default PastelCard;馃搶 Ojo: en tu JSON,
disponibleviene como1o0(porque es unbooleande MySQL). Por eso comparo con=== 1.
7️⃣ Actualizar App.jsx
Reemplaza el contenido de src/App.jsx:
// src/App.jsx
import ListaPasteles from './components/ListaPasteles';
import './App.css';
function App() {
return (
<div className="app">
<ListaPasteles />
</div>
);
}
export default App;8️⃣ Estilos b谩sicos
Reemplaza src/App.css:
.app {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
font-family: system-ui, -apple-system, sans-serif;
}
h1 {
text-align: center;
color: #8b4513;
}
.contador {
text-align: center;
color: #666;
margin-bottom: 2rem;
}
.grid-pasteles {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.pastel-card {
border: 1px solid #eee;
border-radius: 12px;
padding: 1.25rem;
background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: transform 0.2s, box-shadow 0.2s;
}
.pastel-card:hover {
transform: translateY(-4px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
.pastel-card h3 {
margin: 0 0 0.5rem;
color: #333;
font-size: 1.1rem;
}
.sabor {
display: inline-block;
background: #fce4ec;
color: #ad1457;
padding: 0.2rem 0.6rem;
border-radius: 6px;
font-size: 0.8rem;
text-transform: capitalize;
margin-bottom: 0.5rem;
}
.precio {
font-size: 1.4rem;
font-weight: bold;
color: #2e7d32;
margin: 0.5rem 0;
}
.descripcion {
color: #666;
font-size: 0.9rem;
line-height: 1.4;
margin-bottom: 1rem;
}
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
}
.badge.disponible {
background: #e8f5e9;
color: #2e7d32;
}
.badge.agotado {
background: #ffebee;
color: #c62828;
}
.estado {
text-align: center;
font-size: 1.2rem;
margin-top: 4rem;
color: #666;
}
.estado.error {
color: #c62828;
}Y en src/index.css (opcional, para el fondo):
body {
margin: 0;
background: #f9f7f4;
}9️⃣ ⚠️ Configurar CORS en Laravel (CR脥TICO)
Si no haces esto, React no podr谩 conectarse a la API y ver谩s un error de CORS en la consola del navegador:
Access to XMLHttpRequest at 'http://localhost:8000/api/pasteles'
from origin 'http://localhost:5173' has been blocked by CORS policySoluci贸n: configurar CORS en Laravel
En Laravel 11/12 el archivo config/cors.php puede no existir. Publ铆calo:
php artisan config:publish corsAhora edita config/cors.php y aseg煤rate de que tenga:
<?php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:5173'], // puerto por defecto de Vite
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];Y limpia la cach茅 de configuraci贸n:
php artisan config:clear
php artisan cache:clearReinicia el servidor de Laravel:
php artisan serve⚠️ Si quieres permitir cualquier origen (solo en desarrollo, nunca en producci贸n), usa:
'allowed_origins' => ['*'],
馃敓 Ejecutar la aplicaci贸n React
En la terminal del proyecto React:
npm run devVer谩s algo como:
➜ Local: http://localhost:5173/
➜ Network: use --host to exposeAbre tu navegador en http://localhost:5173 y deber铆as ver tu cat谩logo de pasteles. 馃帀
馃И Probar todo el flujo
Con dos terminales abiertas:
Terminal 1 — Laravel:
cd tu-proyecto-laravel
php artisan serve
# → http://localhost:8000Terminal 2 — React:
cd pasteles-app
npm run dev
# → http://localhost:5173Y listo. Si todo est谩 bien, ver谩s los 30 pasteles en formato de tarjetas.
馃悰 Soluci贸n de problemas comunes
| Error | Causa | Soluci贸n |
|---|---|---|
CORS policy blocked | Falta configurar CORS en Laravel | Paso 9 de este tutorial |
Network Error / ERR_CONNECTION_REFUSED | Laravel no est谩 corriendo | Ejecuta php artisan serve |
404 Not Found | URL incorrecta | Verifica http://localhost:8000/api/pasteles en el navegador |
| Los pasteles no aparecen pero no hay error | El JSON tiene forma distinta | Abre la consola y revisa respuesta.data |
| Puerto 5173 ocupado | Otra app usa ese puerto | Vite usar谩 5174 autom谩ticamente, o ci茅rrala |
disponible se ve raro | Viene como 1/0 no true/false | Ya lo manejamos con === 1 en PastelCard |
馃搧 Estructura final del proyecto React
pasteles-app/
├── src/
│ ├── components/
│ │ ├── ListaPasteles.jsx
│ │ └── PastelCard.jsx
│ ├── services/
│ │ └── pastelService.js
│ ├── App.jsx
│ ├── App.css
│ ├── index.css
│ └── main.jsx
├── index.html
├── package.json
└── vite.config.js馃殌 Pr贸ximos pasos (opcional)
Una vez que funcione la lectura, puedes ampliar la app con:
Formulario para crear pasteles — usando
createPastel()que ya definimos.Bot贸n de eliminar — con
deletePastel(id)y unconfirm().Editar — modal con un formulario.
Filtros — por sabor o disponibilidad.
React Router — para tener vistas separadas (lista, detalle, formulario).
Autenticaci贸n con Sanctum — que ya se instal贸 cuando corriste
php artisan install:api.
✅ Resumen de comandos
# 1. Crear app React
npm create vite@latest pasteles-app -- --template react
cd pasteles-app
# 2. Instalar dependencias
npm install
npm install axios
# 3. En Laravel: publicar y configurar CORS
php artisan config:publish cors
# editar config/cors.php
php artisan config:clear
# 4. Ejecutar
npm run devCon esto ya tienes un frontend React consumiendo tu API Laravel de pasteles
Comentarios
Publicar un comentario