Back

htmx en 2026: Cuándo No Necesitás React (Y Cuándo Sí lo Necesitás)

La comunidad frontend lleva dos años discutiendo htmx vs React, y la mayoría de los argumentos están errados. No porque alguna tecnología sea mala, sino porque el debate los pone como competidores que resuelven el mismo problema. Y no es así.

htmx superó las 47,000 estrellas en GitHub. React sigue en millones de aplicaciones en producción. La encuesta State of JS 2025 (publicada en febrero 2026) muestra htmx manteniendo su estatus de "más admirada" entre quienes la probaron, mientras la satisfacción con React cayó a su punto más bajo pese al 83.6% de uso. Algo está cambiando, pero ¿qué exactamente?

Esto no es otro artículo de "htmx bueno, React malo". Es un framework de decisión. Al terminar, vas a saber exactamente cuándo htmx es la elección correcta, cuándo React sigue siendo irremplazable, y cuándo la respuesta es "usá los dos".


La División Arquitectónica Central

Antes de comparar features, necesitás entender la diferencia fundamental. htmx y React no solo usan APIs distintas — representan filosofías diferentes sobre dónde debe vivir el estado de la aplicación.

React: El Modelo de Aplicación Client-Side

React trata al navegador como un runtime de aplicación. Tu servidor es una API que devuelve JSON. Tu cliente es una aplicación completa que maneja estado, routing, renderizado UI y side effects.

[Servidor] → JSON → [App React] → DOM
                        ↑
                Manejo de Estado
                Routing
                Side Effects
                Error Boundaries

Este modelo es poderoso. Permite apps offline-first, actualizaciones optimistas, animaciones complejas, colaboración en tiempo real e interfaces ricas. También es complejo. Una app React típica en 2026 involucra:

  • Un meta-framework (Next.js, Remix o similar)
  • Un approach de manejo de estado (React Context, Zustand, Jotai, o Server Components)
  • Una capa de data fetching (TanStack Query, SWR, o loaders nativos del framework)
  • Un pipeline de build (Vite, Turbopack o Webpack)
  • Configuración de TypeScript
  • Infraestructura de testing (Vitest, Playwright, Testing Library)

Son seis capas de tooling antes de escribir una sola línea de lógica de negocio.

htmx: El Modelo Hipermedia

htmx trata al navegador como un visor de documentos que puede intercambiar partes. Tu servidor devuelve fragmentos HTML. El cliente no tiene estado, ni lógica de routing, ni build step.

[Servidor] → HTML → [Navegador + htmx] → DOM (swap del target)

El servidor es la aplicación. El navegador es el renderer. htmx es el puente que te permite actualizar partes de la página sin recargas completas.

<!-- Formulario de búsqueda que actualiza resultados sin recargar --> <input type="search" name="q" hx-get="/search" hx-trigger="input changed delay:300ms" hx-target="#results"> <div id="results"> <!-- El servidor devuelve fragmentos HTML acá --> </div>

Eso es todo. Sin archivo JavaScript. Sin build step. Sin manejo de estado. El servidor procesa la búsqueda, renderiza los resultados como HTML, y htmx swapea el div #results. La interacción completa se define en atributos HTML.


Donde htmx Gana: El 80% de las Aplicaciones Web

Acá viene la verdad incómoda que a los defensores de React no les gusta escuchar: la mayoría de las apps web son interfaces CRUD con formularios, tablas, filtros y navegación. No necesitan un runtime de aplicación client-side. Necesitan un servidor que renderice HTML y una forma de actualizar partes de la página sin recargar.

1. Dashboards de Admin y Herramientas Internas

La categoría más grande donde htmx domina. Un panel de administración es fundamentalmente una colección de:

  • Tablas con sorting, filtros y paginación
  • Formularios para crear y editar registros
  • Modales de confirmación
  • Toast notifications para feedback

Con htmx, cada uno se resuelve con un round-trip al servidor que devuelve un fragmento HTML:

<!-- Header de tabla sorteable --> <th hx-get="/users?sort=name&dir=asc" hx-target="#user-table-body" hx-indicator="#loading"> Nombre ↕ </th> <!-- Eliminar con confirmación --> <button hx-delete="/users/42" hx-confirm="¿Eliminar este usuario?" hx-target="closest tr" hx-swap="outerHTML swap:500ms"> Eliminar </button> <!-- Edición inline --> <td hx-get="/users/42/edit-name" hx-trigger="dblclick" hx-swap="innerHTML"> Juan Pérez </td>

La misma funcionalidad en React requiere:

// Manejo de estado para sort const [sortConfig, setSortConfig] = useState({ key: 'name', dir: 'asc' }); // Data fetching con TanStack Query const { data, isLoading, refetch } = useQuery({ queryKey: ['users', sortConfig, filters, page], queryFn: () => fetchUsers({ ...sortConfig, ...filters, page }), }); // Mutation de delete con update optimista const deleteMutation = useMutation({ mutationFn: deleteUser, onMutate: async (userId) => { await queryClient.cancelQueries(['users']); const previous = queryClient.getQueryData(['users']); queryClient.setQueryData(['users'], (old) => old.filter(u => u.id !== userId) ); return { previous }; }, onError: (err, userId, context) => { queryClient.setQueryData(['users'], context.previous); }, onSettled: () => queryClient.invalidateQueries(['users']), }); // Estado del modal de confirmación const [deleteTarget, setDeleteTarget] = useState(null); const [showConfirm, setShowConfirm] = useState(false);

La versión htmx son 8 líneas de atributos HTML. La versión React son 25+ líneas de JavaScript antes de tocar el JSX. Y la versión React tiene más puntos de fallo: caché stale, bugs en rollback optimista, race conditions entre queries, y memory leaks de suscripciones.

2. Formularios Multi-paso y Wizards

htmx maneja validación parcial y flujos multi-paso de forma natural porque el servidor controla el estado:

<!-- Paso 1: El servidor valida y devuelve el paso 2 --> <form hx-post="/onboarding/step-1" hx-target="#wizard-container" hx-swap="innerHTML"> <input name="email" type="email" required> <input name="company" required> <button type="submit">Siguiente</button> </form>

El servidor valida el paso 1, guarda el progreso en la sesión y devuelve el HTML del paso 2. Sin manejo de estado de formulario client-side. Sin Formik, sin React Hook Form, sin schemas Zod conectados a componentes del cliente.

3. Sitios de Contenido con Secciones Dinámicas

Blogs, sitios de documentación, páginas de producto de e-commerce — donde el contenido core es server-rendered pero necesitás interacciones dinámicas (agregar al carrito, búsqueda en vivo, secciones de comentarios).

htmx te deja mantener server-side rendering para SEO mientras agregás interactividad targetiada:

<!-- Agregar al carrito sin reload --> <button hx-post="/cart/add" hx-vals='{"productId": "abc123", "qty": 1}' hx-target="#cart-count" hx-swap="innerHTML"> Agregar al Carrito </button> <!-- Sección de comentarios en vivo --> <div hx-get="/posts/42/comments" hx-trigger="load, every 30s" hx-swap="innerHTML"> <!-- Los comentarios se cargan acá --> </div>

El Argumento de Performance

Para aplicaciones server-driven, htmx gana en todas las métricas de rendimiento que importan:

MétricahtmxReact SPA
Bundle de JavaScript~14 KB (htmx en sí)150-400 KB (framework + app)
Time to InteractiveCasi instantáneo (sin hydration)Demorado (requiere hydration)
Score INPExcelente (mínima ejecución JS)Variable (depende del component tree)
Carga del servidorMayor (renderiza HTML)Menor (devuelve JSON)
Cacheabilidad CDNExcelente (fragmentos HTML cachean bien)Pobre (respuestas JSON dinámicas)

La única área donde React gana es carga del servidor. Renderizar HTML server-side cuesta más CPU que serializar JSON. Pero en 2026, con edge computing y streaming HTML, este tradeoff favorece cada vez más a htmx para la mayoría de las aplicaciones.


Donde React Sigue Siendo Irremplazable

Ahora el otro lado. Hay aplicaciones donde htmx genuinamente no puede competir, y hacerse el distraído no es honesto.

1. Editores de Texto Enriquecido y Componentes Interactivos Complejos

Construir algo como Notion, Google Docs, o un whiteboard colaborativo requiere manejar estado local complejo con granularidad de microsegundos. Cada keystroke, posición del cursor, rango de selección y operación de formato debe manejarse client-side. Un round-trip al servidor por cada carácter generaría latencia insoportable.

htmx no puede con esto. Un round-trip de 200ms al servidor por keystroke no es viable. Este es territorio de aplicaciones client-side.

2. Aplicaciones Offline-First

Si tu app necesita funcionar sin internet — como una app de servicio en campo, una app de notas móvil o un sistema POS — htmx es arquitectónicamente incompatible. htmx necesita un servidor para cada interacción. Sin servidor, sin interacción.

3. Features de Colaboración en Tiempo Real

Edición simultánea estilo Google Docs, juegos multiplayer, herramientas de diseño colaborativo — cualquier cosa donde múltiples usuarios modifican estado compartido a alta frecuencia. El modelo request-response de htmx no encaja en este patrón.

4. Interacciones UI de Alta Frecuencia

Drag-and-drop, visualizaciones de datos interactivas (D3.js), UIs con mucha animación, editores canvas y interfaces tipo juego requieren respuesta a frame-rate del lado del cliente.

Matriz de Decisión

Caso de UsohtmxReactAmbos
Dashboards de admin✅ Óptimo⚠️ Overkill
Apps CRUD✅ Óptimo⚠️ Overkill
Formularios multi-paso✅ Bueno✅ Bueno
E-commerce✅ Bueno✅ Bueno✅ Óptimo
Sitios de contenido con interacciones✅ Óptimo⚠️ Overkill
Editores de texto enriquecido❌ No puede✅ Necesario
Apps offline-first❌ No puede✅ Necesario
Colaboración en tiempo real❌ Pobre✅ Necesario
Dashboards de visualización⚠️ Limitado✅ Óptimo✅ Bueno
Builders drag-and-drop❌ No puede✅ Necesario

El Patrón "Usá Ambos": Islas de Interactividad

La respuesta más pragmática en 2026 suele ser "usá los dos". La arquitectura se llama Islas de Interactividad — htmx maneja la estructura de la página, navegación y CRUD estándar, mientras componentes React (o Preact/Svelte) aislados manejan las partes interactivas complejas.

Cómo Funciona

<!-- Shell de página manejado por htmx --> <main> <!-- htmx maneja la navegación --> <nav hx-boost="true"> <a href="/dashboard">Dashboard</a> <a href="/analytics">Analíticas</a> <a href="/settings">Configuración</a> </nav> <!-- htmx maneja la tabla/CRUD --> <section hx-get="/dashboard/table" hx-trigger="load" hx-target="this"> Cargando... </section> <!-- Isla React para el gráfico interactivo --> <div id="analytics-chart" data-config='{"range": "30d", "metrics": ["revenue", "users"]}'> </div> <script type="module"> import { renderChart } from './chart-island.js'; renderChart(document.getElementById('analytics-chart')); </script> </main>

GitHub lleva años usando este patrón — la mayor parte de GitHub es HTML server-rendered con JavaScript específico para componentes interactivos como el editor de código, el file tree y el builder de workflows de Actions.


Migración: Extrayendo React de tu SPA

Si estás considerando mover de una SPA React a htmx, no hagas un rewrite de golpe. Usá el patrón Strangler Fig: reemplazá páginas de a una, empezando por las más simples.

Paso 1: Identificar Páginas de Baja Interacción

Auditá tu app React. Buscá páginas que sean esencialmente tablas de datos con filtros, formularios de configuración, vistas de detalle y vistas de lista/grilla. Probablemente representen entre el 60-80% de tus páginas pero menos del 20% de la complejidad interactiva.

Paso 2: Rutas Server-Side

Para cada candidato, creá una ruta server-side que devuelva HTML completo:

# Ejemplo en Django def user_list(request): users = User.objects.filter(active=True) sort = request.GET.get('sort', 'name') if request.headers.get('HX-Request'): # Petición htmx: devolver solo el body de la tabla return render(request, 'users/_table_body.html', {'users': users}) # Petición de página completa: devolver página entera return render(request, 'users/list.html', {'users': users})

El chequeo del header HX-Request es el patrón clave. Misma ruta, misma lógica, pero htmx recibe un fragmento HTML mientras la navegación directa recibe la página completa.

Paso 3: Mantener React Donde Importa

No migres tus componentes interactivos. Mantené el editor de texto enriquecido en React, el tablero kanban con drag-and-drop, el widget de chat en tiempo real. Envolvelos como islas autocontenidas que montan en páginas server-rendered.

ROI de la Migración

Equipos que migraron SPAs React pesadas en CRUD a htmx reportan consistentemente:

  • 40-60% de reducción en código frontend
  • Entrega de features más rápida para pantallas CRUD estándar
  • Mejora en Core Web Vitals (mejoras en LCP e INP por eliminar hydration)
  • Debugging simplificado (los logs del servidor cuentan toda la historia)

El Factor Backend: htmx Brilla con Ciertos Stacks

Un aspecto subestimado de htmx es cómo desbloquea a los equipos backend. Si tu equipo es principalmente de Go, Python, Ruby, Rust, PHP o Java, htmx les permite construir apps web interactivas sin aprender React.

Ecosistema htmx + Lenguaje Backend

BackendIntegración htmxMotor de TemplatesEjemplos en Producción
GoExcelente (templ, stdlib)templ, html/templateDashboards de infraestructura
Python/DjangoExcelente (django-htmx)Django templatesPaneles admin, CMS
Ruby/RailsExcelente (Turbo + htmx)ERB, HamlInterfaces admin SaaS
Rust/AxumCreciendo (askama, maud)askama, maudDashboards de alto rendimiento
PHP/LaravelExcelente (Blade nativo)BladeAdmin e-commerce, CRM
Java/SpringBueno (Thymeleaf)ThymeleafApps CRUD enterprise

Errores Comunes con htmx (Y Cómo Evitarlos)

1. Tratar htmx Como un Framework Client-Side

El error más grande es manejar estado en el cliente. Si te encontrás escribiendo JavaScript para rastrear qué tab está activo o qué filtros están aplicados, estás peleando contra la arquitectura de htmx.

Mal:

let activeFilters = []; document.querySelectorAll('.filter-checkbox').forEach(cb => { cb.addEventListener('change', () => { if (cb.checked) activeFilters.push(cb.value); else activeFilters = activeFilters.filter(f => f !== cb.value); htmx.ajax('GET', `/items?filters=${activeFilters.join(',')}`, '#results'); }); });

Bien:

<!-- Dejá que el servidor maneje el estado de los filtros --> <form hx-get="/items" hx-target="#results" hx-trigger="change"> <label><input type="checkbox" name="filter" value="active"> Activos</label> <label><input type="checkbox" name="filter" value="premium"> Premium</label> <label><input type="checkbox" name="filter" value="new"> Nuevos</label> </form>

2. Hacer Demasiadas Peticiones

htmx hace que las peticiones al servidor sean fáciles, lo que puede llevar a aplicaciones muy chatty. Usá modificadores de hx-trigger para debounce y throttle:

<input hx-get="/search" hx-trigger="input changed delay:300ms" hx-target="#results" name="q">

3. Olvidarse de los Estados de Carga

htmx provee el patrón hx-indicator para estados de carga. Usalo siempre:

<button hx-post="/process" hx-indicator="#spinner"> Enviar <img id="spinner" class="htmx-indicator" src="/spinner.svg"> </button>

Reality Check 2026

La industria está convergiendo en un punto medio pragmático:

  1. Las SPAs no murieron. Apps complejas e interactivas siguen necesitando frameworks client-side. React, Vue y Svelte no se van a ningún lado.

  2. Las SPAs están sobreusadas. Demasiadas apps que son fundamentalmente CRUD server-driven se construyeron como SPAs client-side porque "así se hace ahora". htmx expone esta sobreingeniería.

  3. La mejor arquitectura es la que se ajusta a tu problema. Un clon de Notion necesita React. Un dashboard de admin necesita htmx. Un producto SaaS probablemente necesite los dos.

  4. htmx no es "volver al pasado". No es desarrollo de la era PHP. Es un enfoque moderno que aprovecha los semánticos HTTP, los navegadores modernos y el hecho de que la mayoría de las interacciones son patrones request-response. La infraestructura de server-rendering de 2026 hace este approach más rápido y escalable que nunca.

  5. La fatiga del ecosistema JavaScript es real. El crecimiento de htmx no es solo mérito técnico. Es también desarrolladores cansados de mantener directorios node_modules de 200MB, debuggear configuraciones de webpack y aprender una nueva librería de manejo de estado cada seis meses.

Elegí la arquitectura basándote en lo que tu aplicación realmente necesita, no en lo que Twitter dice que está de moda. Para la mayoría de las apps web, eso significa menos JavaScript, no más.

htmxReactFrontendArchitectureWeb DevelopmentPerformance

Explora herramientas relacionadas

Prueba estas herramientas gratuitas de Pockit