CodeForge

React 19 de Cero a Experto / React 19 moderno

use(): el hook que rompe las reglas

Teoría20 min20 XP

Todos los hooks que conoces siguen las mismas reglas: solo en el nivel superior, nunca dentro de un if. React 19 introduce uno que las ROMPE a propósito: use(). Puede leer una promesa directamente (y suspender el componente hasta que resuelva), puede leer un contexto, y —único entre los hooks— puede llamarse dentro de condicionales y bucles. Hoy entiendes qué hace, por qué es la excepción, y cómo se conecta con Suspense.

Un hook con pase VIP

Leer una promesa con use()

El uso estelar: use(promesa) "desenvuelve" una promesa y te da su valor resuelto, directamente en el render. Si la promesa aún no resolvió, el componente SE SUSPENDE y React muestra el fallback del <Suspense> que lo envuelve:

use-promesa.tsx
import { use, Suspense } from "react";

// una promesa creada FUERA del componente (o pasada por props / cacheada)
const promesaGastos: Promise<Gasto[]> = fetch("/api/gastos").then((r) => r.json());

function ListaGastos() {
// use() desenvuelve la promesa: si no resolvió, el componente se suspende
const gastos = use(promesaGastos);
return (
  <ul>
    {gastos.map((g) => <li key={g.id}>{g.nombre}: {g.valor}</li>)}
  </ul>
);
}

export default function App() {
return (
  // mientras la promesa de ListaGastos no resuelve, se ve el fallback
  <Suspense fallback={<p>Cargando gastos…</p>}>
    <ListaGastos />
  </Suspense>
);
}

Fíjate en lo que NO hay: ni useState de cargando, ni useEffect, ni el patrón de tres estados de la lección anterior. use(promesaGastos) te da los datos directamente; mientras la promesa está pendiente, <Suspense> muestra "Cargando gastos…"; si la promesa rechaza, un Error Boundary cercano atrapa el error. React coordina el "cargando" y el "error" a nivel de árbol, no componente por componente. (Verás Suspense y Error Boundaries a fondo en el módulo 5.)

Leer un contexto (y condicionalmente)

El otro uso de use(): leer un Context. Aquí sí se nota que rompe las reglas —puede ir dentro de un if, cosa que useContext no permite—:

use-contexto.tsx
import { use } from "react";
import { TemaContext } from "./tema";

function Boton({ destacado }: { destacado: boolean }) {
if (destacado) {
  // ✅ use() PUEDE llamarse dentro de un if (useContext NO podría)
  const tema = use(TemaContext);
  return <button style={{ background: tema.acento }}>Destacado</button>;
}
return <button>Normal</button>;
}

use(TemaContext) lee el contexto igual que useContext(TemaContext), pero al no depender del orden posicional de los hooks, puede vivir dentro de un if o un bucle. Es la razón técnica por la que use no lleva el prefijo de "hook con reglas estrictas" de los demás: internamente React lo maneja distinto. (Verás Context en detalle en el módulo 6; por ahora, quédate con que use es la forma flexible de leerlo.)

¿Qué hace use(promesa) y qué necesita Suspense para funcionar?

Mini-reto

Razona el flujo (o pruébalo en tu proyecto React 19): 1) crea una promesa const datos = obtener() FUERA de un componente; 2) un componente <Panel> que haga const valor = use(datos) y lo muestre; 3) envuélvelo en <Suspense fallback={<Spinner />}>. Pregúntate: ¿qué pasaría si movieras const datos = obtener() DENTRO del componente? (Pista: una promesa nueva por render.) ¿Y quién muestra el "cargando"?

Qué sigue

use() insinúa un mundo donde el render puede "esperar" datos. Ese mundo se despliega del todo con los SERVER COMPONENTS: componentes que corren en el servidor, sin llegar nunca al navegador como JavaScript. La próxima lección explica el concepto —Server Components vs Client Components— que redefine dónde vive tu código en React moderno.