REACT CONSUMO DE API
Consumir una API desde cero (paso a paso)
Vamos a ir de lo más simple a lo más realista, ejemplo por ejemplo. Al final entenderás por qué aparecen promesas, setTimeout, useEffect, axios y fetch.
🧩 Ejemplo 1 — Solo un arreglo, sin nada de React
Este es el punto de partida. Un arreglo es solo una lista de datos en memoria.
function App() {
const datos = [
{ id: 1, nombre: 'Ana' },
{ id: 2, nombre: 'Luis' },
{ id: 3, nombre: 'Carlos' },
{ id: 4, nombre: 'María' },
{ id: 5, nombre: 'Pedro' },
];
return (
<div>
<h1>Lista de usuarios</h1>
<ul>
{datos.map((item) => (
<li key={item.id}>{item.nombre}</li>
))}
</ul>
</div>
);
}Qué aprendes aquí:
Cómo recorrer un arreglo con
.map().Cómo renderizar una lista en React.
No hay API, no hay promesa, no hay espera. Los datos ya están ahí.
✅ Esto es lo más básico. Pero no se parece a una API real, porque una API:
Tarda un tiempo en responder.
Devuelve los datos después, no de inmediato.
Puede fallar.
🧩 Ejemplo 2 — Simular que la API "tarda" con setTimeout
Aquí es donde empieza a parecerse a la realidad.
const fakeApi = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ id: 1, nombre: 'Ana' },
{ id: 2, nombre: 'Luis' },
{ id: 3, nombre: 'Carlos' },
{ id: 4, nombre: 'María' },
{ id: 5, nombre: 'Pedro' },
]);
}, 1000); // ⏱️ 1 segundo de "espera"
});
};Por qué se usa setTimeout aquí:
Una API real no responde instantáneamente. Tarda milisegundos o segundos.
setTimeoutsimula ese retraso.Dentro del
setTimeout, llamamos aresolve(...)con los datos. Eso significa: "ya terminé, aquí está la respuesta".
Por qué se usa una Promise:
Una promesa es un objeto que representa un valor que estará disponible en el futuro.
Una API real (con
fetchoaxios) siempre devuelve una promesa. Por eso la simulamos así.La promesa tiene 3 estados:
pending(esperando)fulfilled(resuelta con datos)rejected(falló)
En resumen: setTimeout simula el tiempo, la Promise simula el mecanismo de una API real.
🧩 Ejemplo 3 — Tu duda: promesa sin setTimeout
const fakeApi = () => {
return Promise.resolve([
{ id: 1, nombre: 'Ana' },
// ...
]);
};❓ ¿Por qué usan una promesa si no hay setTimeout?
Buena pregunta. Aquí está la clave:
La promesa no está simulando el tiempo. Está simulando la forma en que una API entrega los datos.
Aunque los datos estén listos al instante, una API real nunca te los da directamente. Te da una promesa que tienes que resolver con .then() o await.
Entonces:
| Elemento | Qué simula |
|---|---|
setTimeout | El tiempo que tarda la API en responder |
Promise | El mecanismo con el que la API entrega los datos |
Promise.resolve([...]) | Una API que responde al instante, pero sigue siendo una promesa |
👉 Es como decir: "No quiero simular el retraso, pero sí quiero que el código que consume los datos se vea igual que si fuera una API real."
Por eso el .then() sigue existiendo:
fakeApi().then((respuesta) => {
setDatos(respuesta);
});Ese .then() es exactamente el mismo que usarías con fetch o axios. Eso es lo valioso: practicas el patrón real sin esperar.
🧩 Ejemplo 4 — Con useEffect + useState (el patrón real)
function App() {
const [datos, setDatos] = useState([]);
const [cargando, setCargando] = useState(true);
useEffect(() => {
fakeApi().then((respuesta) => {
setDatos(respuesta);
setCargando(false);
});
}, []);
if (cargando) return <p>Cargando...</p>;
return (
<ul>
{datos.map((item) => (
<li key={item.id}>{item.nombre}</li>
))}
</ul>
);
}Por qué esto es importante:
useEffectse ejecuta después de que el componente se monta. Ahí es donde pides datos.useStateguarda los datos cuando llegan.cargandomuestra un mensaje mientras esperas.
Este patrón es idéntico al que usarás con fetch o axios. Solo cambia fakeApi() por la llamada real.
🧩 Ejemplo 5 — Con fetch (API real)
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => res.json())
.then((data) => {
setDatos(data);
setCargando(false);
});
}, []);Aquí ya no hay simulación. fetch:
Devuelve una promesa.
Tarda lo que tarde la red.
Puede fallar.
Fíjate que el .then() es el mismo que usaste en los ejemplos simulados. Por eso vale la pena practicar con fakeApi.
🧩 Ejemplo 6 — Con axios (más limpio)
import axios from 'axios';
useEffect(() => {
axios.get('https://jsonplaceholder.typicode.com/users')
.then((res) => {
setDatos(res.data); // 👈 axios ya te da el JSON listo
setCargando(false);
});
}, []);Diferencia con fetch:
fetchrequiereres.json()como segundo paso.axiosya te dares.datadirectamente.Ambos devuelven promesas.
🧩 Ejemplo 7 — Con async/await (más legible)
useEffect(() => {
const cargarDatos = async () => {
try {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const data = await res.json();
setDatos(data);
} catch (error) {
console.error(error);
} finally {
setCargando(false);
}
};
cargarDatos();
}, []);async/await es azúcar sintáctico sobre las promesas. Hace lo mismo, pero se lee como código síncrono.
📊 Resumen final
| Ejemplo | Qué simula | ¿Parece API real? | ¿Ves "Cargando..."? |
|---|---|---|---|
| 1. Arreglo directo | Nada | ❌ | ❌ |
2. setTimeout + Promise | Tiempo + mecanismo | ✅✅ | ✅ |
3. Promise.resolve | Solo mecanismo | 🟡 | ❌ |
4. useEffect + useState | Patrón real | ✅ | ✅ |
5. fetch | API real | ✅✅✅ | ✅ |
6. axios | API real | ✅✅✅ | ✅ |
7. async/await | API real | ✅✅✅ | ✅ |
🎯 Respuesta directa a tu duda
"¿Por qué usan una promesa si no hay setTimeout?"
Porque la promesa no simula el tiempo, simula la API. Una API real siempre te devuelve una promesa, aunque responda rápido. Al usar Promise.resolve([...]):
Practicas el mismo
.then()que usarás confetch/axios.Evitas esperar 1 segundo en cada prueba.
El código que consume los datos es idéntico al real.
setTimeout es solo un extra para simular el retraso. Si no lo pones, el patrón sigue siendo válido, solo que el mensaje "Cargando..." casi no se ve.
🚀 Ruta recomendada para ti
Haz el Ejemplo 1 hasta que lo entiendas bien (
.map,key).Pasa al Ejemplo 3 (promesa sin
setTimeout) y observa el.then().Añade
setTimeout(Ejemplo 2) para ver "Cargando...".Reemplaza
fakeApiporfetch(Ejemplo 5) con JSONPlaceholder.Prueba
axios(Ejemplo 6).Refactoriza a
async/await(Ejemplo 7).
¿Quieres que te arme el Ejercicio 1 completo con JSONPlaceholder para que lo copies y lo pruebes ahora mismo
Vamos paso por paso (y sin enredos)
Tu intuición va bien encaminada, pero hay dos ideas que hay que separar:
Qué es una promesa (el mecanismo).
Qué es
setTimeout(el temporizador).
No son lo mismo. Y no se "usan juntas por obligación". Vamos a verlo con ejemplos mínimos.
🔹 Idea clave antes de empezar
Una promesa es un objeto que dice:
"Todavía no tengo el valor, pero te aviso cuando lo tenga (o si falla)."
Un setTimeout es una función que dice:
"Ejecuta este código después de X milisegundos."
Son cosas distintas. Se pueden combinar, pero ninguna necesita a la otra.
🧩 Ejemplo A — Solo setTimeout, SIN promesa
setTimeout(() => {
console.log('Pasaron 2 segundos');
}, 2000);Qué pasa aquí:
No hay promesa.
No hay
.then().No hay
await.Simplemente, después de 2 segundos, se ejecuta el
console.log.
✅ Tu intuición es correcta: setTimeout por sí solo no necesita promesa.
🧩 Ejemplo B — Solo promesa, SIN setTimeout
const promesa = Promise.resolve('Hola mundo');
promesa.then((valor) => {
console.log(valor); // "Hola mundo"
});Qué pasa aquí:
No hay
setTimeout.La promesa ya está resuelta desde el inicio.
Pero el
.then()siempre se ejecuta después, aunque la promesa esté lista. Esto se debe al microtask queue de JavaScript.
✅ Aquí ves que una promesa no necesita setTimeout para funcionar.
🧩 Ejemplo C — Los dos juntos (el caso del tutorial)
const fakeApi = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([{ id: 1, nombre: 'Ana' }]);
}, 1000);
});
};Aquí sí se combinan, pero cada uno hace su trabajo:
| Elemento | Qué hace |
|---|---|
new Promise(...) | Crea el "contenedor" que avisará cuando haya datos |
setTimeout(...) | Simula el tiempo que tarda la API en responder |
resolve(...) | Entrega los datos y marca la promesa como resuelta |
No es que la promesa necesite a setTimeout. Es que aquí usamos setTimeout como herramienta para que la promesa tarde en resolverse, imitando una API real.
🧠 Ahora tu pregunta concreta
"Veo que también usas promesas cuando envías la contestación y cuando la recibes. ¿Por qué?"
Vamos a desglosarlo porque ahí está la clave.
1. "Cuando envías la contestación"
Cuando escribes:
return new Promise((resolve) => { ... });Lo que haces es devolver una promesa desde fakeApi. Eso significa:
"Oye, quien me llame, no va a recibir los datos directamente. Va a recibir una promesa."
Esto no es enviar la contestación. Es prometer que habrá una contestación.
La contestación real se envía cuando llamas a resolve([...]).
2. "Cuando la recibes"
Cuando escribes:
fakeApi().then((respuesta) => { ... });Ahí recibes la contestación. El .then() es el mecanismo para escuchar cuándo la promesa se resuelve.
3. ¿Por qué promesa en ambos lados?
Porque una promesa es un contrato entre dos partes:
Quien la crea (tu
fakeApi): se compromete a avisar cuando tenga el resultado.Quien la consume (tu
useEffect): se compromete a esperar ese aviso con.then()oawait.
Si solo usaras setTimeout sin promesa, no habría forma de que el consumidor supiera cuándo llegaron los datos. Solo tendrías un console.log dentro del setTimeout, pero no podrías pasar esos datos a otra parte del código.
Ejemplo de eso (sin promesa, no sirve para React):
const fakeApi = () => {
setTimeout(() => {
const datos = [{ id: 1, nombre: 'Ana' }];
// 😕 ¿Cómo le paso esto a React?
// No puedo. Se queda aquí adentro.
}, 1000);
};Con promesa:
const fakeApi = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([{ id: 1, nombre: 'Ana' }]);
// ✅ Ahora sí puedo entregar los datos afuera
}, 1000);
});
};Esa es la razón real de la promesa: no es "para que no marque error", es para poder entregar los datos cuando estén listos, sin importar cuándo lleguen.
🧩 Comparación directa
| Situación | ¿Necesito promesa? | ¿Necesito setTimeout? |
|---|---|---|
| Solo quiero ejecutar algo después de un tiempo | ❌ | ✅ |
| Solo quiero entregar un valor "ya listo" pero de forma asíncrona | ✅ | ❌ |
| Simular una API que tarda 1 segundo | ✅ | ✅ |
Consumir fetch o axios reales | ✅ (ya viene incluida) | ❌ |
🧩 Ejemplo final que une todo (comentado)
// 1. Creo la función que simula la API
const fakeApi = () => {
// 2. Devuelvo una promesa: "te avisaré cuando tenga datos"
return new Promise((resolve) => {
// 3. Uso setTimeout para simular el retraso de la red
setTimeout(() => {
// 4. Cuando "llega" la respuesta, la entrego con resolve
resolve([
{ id: 1, nombre: 'Ana' },
{ id: 2, nombre: 'Luis' },
]);
}, 1000);
});
};
// 5. Consumo la promesa: "avísame cuando tengas datos"
fakeApi().then((respuesta) => {
console.log('Datos recibidos:', respuesta);
});Léelo así:
Línea 4: "Te prometo que habrá datos."
Línea 6: "Pero tardarán 1 segundo (simulado)."
Línea 8: "Aquí están los datos, promesa cumplida."
Línea 17: "Cuando se cumpla, haz esto con los datos."
✅ Resumen en una frase
setTimeoutsimula el tiempo. La promesa simula el contrato de una API.
No se necesitan entre sí, pero juntas imitan perfectamente a una API real: una que tarda y que te avisa cuando termina.
¿Quieres que te arme un ejemplo donde solo uses setTimeout sin promesa dentro de React, para que veas por qué no funciona y así entiendas la necesidad de la promesa
¿Por qué uso setTimeout?
Buena pregunta. Lo uso solo para simular la demora de una API real. No es obligatorio ni es parte de React, es un truco didáctico.
🎯 El motivo principal: simular asincronía
Una API real no responde instantáneamente. Tarda milisegundos o incluso segundos en devolver los datos. Ejemplo con fetch real:
jsx
fetch('https://api.ejemplo.com/usuarios')
.then(res => res.json())
.then(data => console.log(data));
Aquí, entre que haces la petición y recibes los datos, pasa un tiempo. Ese tiempo es la "espera de red".
🧪 ¿Qué pasa si NO uso setTimeout?
Si devolvemos los datos de inmediato, perdemos el realismo:
jsx
const fakeApi = () => {
return Promise.resolve([
{ id: 1, nombre: 'Ana' },
// ...
]);
};
Esto funciona, pero es instantáneo. Y ahí hay un problema didáctico:
No verías el estado cargando = true en acción (pasaría tan rápido que ni lo notarías).
No practicarías cómo manejar el "mientras espero, muestro un spinner".
No entenderías bien por qué necesitas useEffect + useState.
Con setTimeout(..., 1000) obligas a que haya una espera real de 1 segundo, y así puedes ver en pantalla:
text
Cargando...
...y luego:
text
• Ana
• Luis
• Carlos
• María
• Pedro
🔄 Comparación visual
🧠 En resumen
setTimeout no es necesario para que el código funcione. Lo uso porque:
Simula la latencia de una API real.
Te permite ver el estado de carga funcionando.
Hace que el ejemplo se parezca más a lo que pasarás en un proyecto real.
💡 Alternativa más limpia
Si quieres simular sin setTimeout, puedes usar async/await con una promesa normal:
jsx
const fakeApi = async () => {
return [
{ id: 1, nombre: 'Ana' },
{ id: 2, nombre: 'Luis' },
// ...
];
};
Pero vuelve a ser instantáneo. Si quieres realismo y código limpio, esta es la mejor forma:
jsx
const fakeApi = async () => {
await new Promise(res => setTimeout(res, 1000)); // espera 1s
return [
{ id: 1, nombre: 'Ana' },
// ...
];
};
Así separas claramente: "esto es la espera falsa" y "esto son los datos".
¿Quieres que te muestre el mismo ejemplo pero usando async/await en el componente en lugar de .then()
Comentarios
Publicar un comentario