Problema/Solución
30 problemas comunes de React 19 que enfrentan los desarrolladores, cada uno con una solución concisa. Ordenados por frecuencia de más a menos común.
Busca en todas las páginas de la documentación
30 problemas comunes de React 19 que enfrentan los desarrolladores, cada uno con una solución concisa. Ordenados por frecuencia de más a menos común.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
forwardRef se siente redundante después de actualizarProblema: Tienes docenas de componentes forwardRef que ahora se sienten como boilerplate.
Solución: Acepta ref como una prop regular.
interface InputProps extends React.ComponentPropsWithoutRef<"input"> {
ref?: React.Ref<HTMLInputElement>;
}
export function Input({ ref, ...props }: InputProps) {
return <input ref={ref} {...props} />;
}useFormState rotaProblema: useFormState de react-dom advierte o falla.
Solución: Importa useActionState de react - la misma firma más isPending.
import { useActionState } from "react";
const [state, action, isPending] = useActionState(submit, null);Problema: El código que funcionaba en React 18 ahora lanza errores de hidratación.
Solución: Mueve window, Date.now(), Math.random() dentro de useEffect o un hijo solo para cliente.
<title> y <meta> duplicándoseProblema: react-helmet + la elevación de metadatos nativa de React 19 produce etiquetas duplicadas.
Solución: Elimina react-helmet. Renderiza <title>/<meta> directamente en cualquier lugar - React 19 los eleva.
Problema: Los errores lanzados dentro de Server Actions aparecen como Server Error sin stack en producción.
Solución: Devuelve errores como valores, no excepciones.
"use server";
export async function save(_: State, fd: FormData) {
const title = fd.get("title");
if (!title) return { error: "Título requerido" };
return { ok: true };
}use(promise) causando suspense infinitaProblema: El componente se suspende para siempre después de agregar use().
Solución: La promesa debe ser estable entre renderizaciones - créala en un padre o memoízala.
const userPromise = useMemo(() => fetchUser(id), [id]);
const user = use(userPromise);Problema: Marcar un Client Component como async lanza "async/await aún no es compatible".
Solución: Los componentes asincronos son solo en el servidor. Obtén datos en el servidor, pasa como prop, o usa use() en el cliente.
useOptimistic parpadea hacia atrásProblema: La interfaz de usuario optimista se revierte antes de que el servidor responda.
Solución: Envuelve la mutación en startTransition o llámala desde un Server Action.
startTransition(async () => {
addOptimistic(item);
await saveItem(item);
});Problema: <MyContext.Provider value={...}> se siente verboso.
Solución: Renderiza el contexto mismo - React 19 acepta <MyContext value={...}>.
Problema: Sin hook de desmontaje cuando se desmonta un ref del DOM.
Solución: Devuelve una función de limpieza desde el callback del ref.
<div ref={(node) => {
const ob = new ResizeObserver(() => {});
if (node) ob.observe(node);
return () => ob.disconnect();
}} />Problema: Los campos del formulario mantienen sus valores después de un Server Action exitoso.
Solución: Reinicia vía form.reset() en un requestFormReset dentro de la acción, o usa una prop key no controlada.
<form key={submitCount} action={action}>...</form>useActionStateProblema: Pasar undefined como estado inicial rompe el primer renderizado.
Solución: Siempre pasa un valor por defecto explícito como null u {}.
useFormStatus siempre devuelve pending: falseProblema: useFormStatus() llamado en el padre del <form> nunca se actualiza.
Solución: Solo lee el estado de un <form> ancestro. Llámalo desde un hijo renderizado dentro del formulario.
Problema: Devolver Date, Map, o instancias de clase silenciosamente rompe.
Solución: Devuelve solo objetos planos compatibles con JSON.
<head>Problema: <title> se renderiza tarde cuando está dentro de un árbol suspendido.
Solución: Eleva metadatos por encima del límite de Suspense - los layouts son ideales.
forwardRef pierden inferencia de TSProblema: Convertir un forwardRef genérico a prop ref pierde la inferencia de tipos.
Solución: Mantén forwardRef para ese componente, o ajusta la restricción genérica.
useTransition no aplazando renderizaciones costosasProblema: La interfaz de usuario sigue paradeando incluso después de envolver en startTransition.
Solución: Asegúrate de que el trabajo costoso lee del estado actualizado dentro de la transición, no un setState síncrono separado.
Problema: Importar una librería solo para navegador en un Server Component lanza window is not defined.
Solución: Agrega "use client" en la parte superior del archivo, o importa dinámicamente con next/dynamic + ssr: false.
cache() no deduplicando entre solicitudesProblema: cache() de React parece cachear por solicitud pero no entre solicitudes.
Solución: Eso es por diseño - cache() es memoización por solicitud. Para entre solicitudes, usa unstable_cache (Next.js) o un caché externo.
use() en un condicional después de hooks da errorProblema: Llamar use() dentro de un if después de otro hook rompe las reglas de hooks.
Solución: use() puede ser condicional, pero sigue contando como una llamada a hook - mantenlo antes de cualquier retorno anticipado.
Problema: Server Action se ejecuta dos veces en desarrollo.
Solución: Esa es la invocación doble intencional de Strict Mode. Haz las acciones idempotentes o deshabilita Strict Mode solo como último recurso.
ref como prop + librería de terceros esperando forwardRefProblema: Una librería envuelve tu componente y espera semántica de forwardRef.
Solución: Mantén forwardRef en el límite de integración - la compatibilidad sigue funcionando.
useDeferredValueProblema: En el primer renderizado quieres omitir el valor antiguo.
Solución: React 19 acepta un segundo argumento: useDeferredValue(value, initialValue).
const deferred = useDeferredValue(query, "");Problema: El fallback parpadea incluso para transiciones rápidas.
Solución: Envuelve la navegación en startTransition para que React muestre contenido antiguo en lugar del fallback.
<link rel="stylesheet"> cargando fuera de ordenProblema: Múltiples componentes renderizadores de la misma hoja de estilo y el orden es inestable.
Solución: Usa la prop precedence - React 19 deduplica y las ordena.
<link rel="stylesheet" href="/a.css" precedence="default" />Problema: Inyectas <link rel="preload"> a mano y se ejecuta muy tarde.
Solución: Usa las APIs de recursos de React 19: preload, preinit, prefetchDNS de react-dom.
import { preload } from "react-dom";
preload("/hero.jpg", { as: "image" });Problema: El error de Server Action pasa por alto tu <ErrorBoundary>.
Solución: Los límites de error capturan errores de renderizado, no rechazo de acciones. Expón errores vía valor de retorno de useActionState en su lugar.
action={serverAction}Problema: TS se queja de pasar una función del servidor a action.
Solución: Asegúrate de @types/react ≥ 19 y que la firma de acción coincida con (formData: FormData) => void | Promise<void>.
"use server" filtrando código del clienteProblema: Importar utilidades compartidas en un archivo "use server" agrupa código solo para cliente del lado del servidor.
Solución: Mantén los archivos "use server" enfocados en acciones - extrae lógica compartida a un archivo neutral lib/ sin importaciones de React.
ReactDOM.render heredadoProblema: El código de bootstrap antiguo usando ReactDOM.render ya no compila.
Solución: Cambia a createRoot (requerido desde 18, aplicado en 19).
import { createRoot } from "react-dom/client";
createRoot(document.getElementById("root")!).render(<App />);Revisado por Chris St. John·Última actualización: 16 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥