Características de React 19
Hook use(), Actions, useFormStatus, useOptimistic y el Compilador de React
Novedades en React 19
React 19 es una versión mayor que introduce nuevos primitivos para manejar operaciones asíncronas, formularios y actualizaciones optimistas. Estas características simplifican patrones que antes requerían código repetitivo complejo o librerías externas.
🚀 Características Clave de React 19
- use() — Leer promesas y contexto en el renderizado
- Actions — Transiciones asíncronas con estados pendientes automáticos
- useFormStatus() — Rastrear el estado de envío de formularios
- useOptimistic() — Actualizaciones optimistas de UI
- useActionState() — Gestionar estado y errores de acciones
- Compilador React — Memoización automática
- ref como prop — Ya no se necesita forwardRef
El Hook use()
use() permite leer el valor de una Promesa o Contexto directamente durante el renderizado. A diferencia de otros hooks, use() puede llamarse dentro de condicionales y bucles.
import { use, Suspense } from 'react';
function UserProfile({ userPromise }) {
const user = use(userPromise); // Suspende hasta que la promesa se resuelve
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
function App() {
const userPromise = fetchUser(1);
return (
<Suspense fallback={<p>Cargando usuario...</p>}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
useActionState
useActionState gestiona el ciclo completo de una acción de formulario — estado, estado pendiente y manejo de errores en un solo hook:
import { useActionState } from 'react';
async function addTodo(previousState, formData) {
const title = formData.get('title');
if (!title) {
return { error: 'El titulo es requerido', todos: previousState.todos };
}
const newTodo = await saveTodo({ title });
return { error: null, todos: [...previousState.todos, newTodo] };
}
function TodoForm() {
const [state, formAction, isPending] = useActionState(addTodo, {
error: null, todos: [],
});
return (
<form action={formAction}>
<input name="title" placeholder="Nueva tarea..." />
<button disabled={isPending}>
{isPending ? 'Agregando...' : 'Agregar Tarea'}
</button>
{state.error && <p className="text-red-500">{state.error}</p>}
</form>
);
}
useOptimistic
useOptimistic muestra un estado optimista (predicho) mientras una acción asíncrona está en progreso:
import { useOptimistic, useTransition } from 'react';
function MessageList({ messages, sendMessage }) {
const [optimisticMessages, addOptimistic] = useOptimistic(
messages,
(currentMessages, newMessage) => [
...currentMessages,
{ ...newMessage, sending: true },
]
);
const [, startTransition] = useTransition();
async function handleSend(formData) {
const text = formData.get('message');
startTransition(async () => {
addOptimistic({ id: Date.now(), text, sending: true });
await sendMessage(text);
});
}
return (
<div>
{optimisticMessages.map(msg => (
<div key={msg.id} className={msg.sending ? 'opacity-60' : ''}>
{msg.text}
{msg.sending && <span className="text-xs"> (enviando...)</span>}
</div>
))}
<form action={handleSend}>
<input name="message" />
<button>Enviar</button>
</form>
</div>
);
}
ref como Prop (Sin forwardRef)
// React 18 — necesitaba forwardRef
const Input = forwardRef(function Input(props, ref) {
return <input ref={ref} {...props} />;
});
// React 19 — ref es solo un prop!
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
✅ Consejos de Migración
- • React 19 es retrocompatible — el código existente sigue funcionando
- • Comienza reemplazando
forwardRefcon ref-como-prop - • Adopta
useActionStatepara formularios en código nuevo - • Usa
useOptimisticpara reemplazar patrones manuales de actualizaciones optimistas - • El Compilador de React es opt-in — actívalo por archivo o carpeta