React y Vue son herramientas de JavaScript para construir interfaces de usuario a partir de componentes (React se llama a sí mismo librería, Vue framework progresivo), y comparten la mayoría de las ideas: props hacia abajo, eventos hacia arriba, estado reactivo, un DOM virtual. Las diferencias prácticas son que React escribe el marcado en JSX y espera que el estado se reemplace con un setter, mientras que Vue escribe el marcado en plantillas HTML dentro de componentes de un solo archivo y te deja cambiar los valores reactivos directamente. Aquí tienes un contador en React:
Y el mismo contador como componente de un solo archivo de Vue (Counter.vue):
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">Clicked {{ count }} times</button>
</template>
useState(0) pasa a ser ref(0), onClick pasa a ser @click, y {count} pasa a ser {{ count }}. La diferencia visible es count++: Vue te deja cambiar el valor en su lugar, y su sistema de reactividad lo nota. React necesita setCount porque solo vuelve a renderizar cuando le entregas un valor nuevo.
JSX vs componentes de un solo archivo
Un componente de React es una función de JavaScript que devuelve JSX. Las condiciones son && o un ternario, las listas son .map(), y los estilos vienen de lo que elijas (archivos CSS, CSS modules, un framework de utilidades).
Un componente de Vue suele ser un archivo .vue con tres bloques: <script setup> para la lógica, <template> para el marcado y un <style scoped> opcional cuyo CSS se aplica solo a ese componente. Las plantillas usan directivas: v-if, v-for, v-model para el binding bidireccional de inputs, :prop para enlazar un valor y @event para escuchar. Las plantillas mantienen el marcado legible para cualquiera que sepa HTML; JSX te da todo JavaScript en el marcado. Vue también puede usar JSX y React no puede usar plantillas, pero la mayor parte del código de cada uno sigue su opción por defecto.
Aquí tienes una lista filtrada, la segunda funcionalidad a comparar.
Prueba a escribir xyz para ver el mensaje de lista vacía, y luego bórralo. La versión de Vue:
<script setup>
import { ref, computed } from 'vue';
const fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Peach'];
const query = ref('');
const visible = computed(() =>
fruits.filter((f) => f.toLowerCase().includes(query.value.toLowerCase()))
);
</script>
<template>
<input v-model="query" placeholder="Filter fruit" />
<ul>
<li v-for="fruit in visible" :key="fruit">{{ fruit }}</li>
<li v-if="visible.length === 0">No match</li>
</ul>
</template>
v-model reemplaza el par value más onChange, y computed reemplaza la variable simple. En React, visible se vuelve a calcular en cada renderizado porque la función del componente se vuelve a ejecutar; en Vue, computed lo guarda en caché y lo vuelve a calcular solo cuando cambia query. Ambos usan una key para distinguir los elementos de la lista.
El modelo de reactividad
Esta es la diferencia más profunda entre los dos.
React: estado inmutable y nuevos renderizados. El estado es una instantánea. Llamas a un setter con un valor nuevo, React vuelve a ejecutar la función del componente, compara el JSX nuevo con el viejo y actualiza el DOM. React compara los valores con Object.is, así que cambiar un objeto o array en su lugar y devolver el mismo parece que no hubo ningún cambio.
Haz clic en "push() in place" y nada cambia en pantalla, porque el array es el mismo objeto. Luego haz clic en "New array": el renderizado también muestra pushed, porque la mutación anterior sí ocurrió, solo que React no tenía motivo para mirar. La página de useState cubre este patrón en profundidad.
Vue: valores reactivos mutables. Una ref o un objeto reactive registra quién lo lee (una ref mediante su getter .value, un objeto reactive mediante un proxy). Cuando escribes en él, Vue sabe exactamente qué valores computados, watchers y partes de la plantilla dependen de él y actualiza solo esos. En Vue, items.value.push('pushed') actualiza la pantalla. Escribes menos ceremonia, y renuncias a la garantía de que un valor nunca cambia sin que lo sepas.
Ninguno de los dos modelos es más rápido de una forma que importe en apps típicas. React puede ejecutar más código de componentes por cambio y depende de la memoización (a mano, o mediante el React Compiler) para ahorrar trabajo; Vue sigue las dependencias en tiempo de ejecución, así que ahorra ese trabajo por defecto.
Composition API vs hooks
La Composition API de Vue 3 y los hooks de React resuelven el mismo problema: juntar el estado y la lógica relacionados y reutilizarlos entre componentes. Vue llama composables a las funciones reutilizables (useMouse()), React las llama hooks personalizados (useMouse()). Las reglas difieren por el momento en que se ejecuta el código.
- Cuándo se ejecuta. Un
setupde Vue se ejecuta una vez cuando se crea el componente. Una función de componente de React se ejecuta en cada renderizado, y los hooks que contiene se ejecutan con ella. - Reglas de orden. React empareja los hooks por el orden de llamada, así que no puedes llamarlos dentro de condiciones o bucles. Vue no tiene esa regla para
refycomputed, porque setup se ejecuta una vez. - Dependencias. Los efectos y memos de React enumeran sus dependencias en un array que mantienes tú.
watchEffectycomputedde Vue siguen automáticamente lo que leen. - Valores viejos. Un callback de React puede capturar un valor de estado viejo de un renderizado anterior (el clásico error de
setInterval). Un callback de Vue leecount.valueen el momento de la llamada y siempre ve el valor actual.
El modelo de React hace que cada renderizado sea una función pura de las props y el estado, fácil de probar y de razonar. El modelo de Vue elimina un tipo de errores relacionados con los arrays de dependencias. Quien conoce uno suele aprender el otro rápido.
Ecosistema
| React | Vue | |
|---|---|---|
| Marcado | JSX | Plantillas HTML en archivos .vue (JSX opcional) |
| Actualizaciones de estado | Reemplazar con un setter y volver a renderizar | Cambiar un valor reactivo, se actualiza lo que depende de él |
| Reutilizar lógica | Hooks personalizados | Composables |
| Valores derivados | Calculados durante el renderizado, useMemo | computed (en caché) |
| Binding bidireccional de inputs | value más onChange | v-model |
| CSS con ámbito | No integrado (CSS modules, librerías) | <style scoped> integrado |
| Enrutamiento | React Router, TanStack Router, frameworks | Vue Router (oficial) |
| Estado global | Contexto, Zustand, Redux Toolkit | Pinia (oficial) |
| Framework full-stack | Next.js, React Router en modo framework | Nuxt |
| Apps móviles | React Native | Sin opción oficial (Capacitor, NativeScript-Vue) |
| Herramienta de build | Vite o un framework | Vite |
| Mantenido por | Meta y la comunidad | Un equipo principal independiente y la comunidad |
El patrón de esa tabla: el equipo principal de Vue mantiene juntos el router, el store y las devtools, así que un proyecto de Vue tiene una opción por defecto obvia para cada uno. React deja eso a la comunidad, lo que te da más opciones y más decisiones. Vite, la herramienta de build habitual para proyectos nuevos en ambos, la empezó el creador de Vue.
Curva de aprendizaje
Vue suele ser un comienzo más suave. Las plantillas se leen como el HTML que ya conoces, v-model elimina el código repetitivo de los inputs controlados, y un valor reactivo actualiza la pantalla cuando lo cambias. React pide desde el principio JSX y el hábito de las actualizaciones inmutables, y la página de JSX es lo primero que necesita la mayoría.
Después de lo básico, la distancia se reduce. Vue agrega sus propios conceptos (refs vs objetos reactivos, .value en los scripts pero no en las plantillas, watchers), y React agrega efectos, memoización y las reglas de los hooks. Las ofertas de trabajo de tu zona desempatan mejor que la sintaxis.
Cuándo elegir cuál
Elige React cuando:
- Quieres una amplia variedad de librerías y componentes de la comunidad, o piensas construir apps móviles nativas con React Native.
- Te gusta tener la lógica y el marcado en una sola función de JavaScript y quieres un framework como Next.js.
- Tu equipo valora las actualizaciones explícitas e inmutables que hacen fácil seguir cada renderizado.
Elige Vue cuando:
- Quieres herramientas oficiales y coordinadas para el enrutamiento y el estado, y menos decisiones que tomar.
- Tu equipo incluye diseñadores o desarrolladores backend que se sienten cómodos con plantillas HTML.
- Estás agregando interactividad a páginas existentes renderizadas en el servidor: Vue se puede incluir en una página con una etiqueta script y crecer desde ahí.
Ambos son maduros y los usan en producción empresas de todos los tamaños, y los conceptos que aprendes en uno (componentes, props, estado derivado, listas con key) se trasladan directamente al otro.
Preguntas frecuentes
¿Vue es más fácil que React?
Muchos principiantes encuentran Vue más fácil al principio, porque las plantillas parecen HTML normal y cambiar un valor reactivo (count.value++) actualiza la pantalla sin un setter. React te pide aprender JSX y la regla de que el estado se reemplaza, no se modifica. Después de las primeras semanas la dificultad es parecida.
¿Qué es mejor, React o Vue?
Ninguno gana en general. React deja el enrutamiento y el estado a librerías de la comunidad y tiene React Native para móvil. Vue tiene un router, un store y unas devtools oficiales mantenidos juntos, y plantillas que a mucha gente le resultan más fáciles de leer. Elige el que use tu equipo o tu mercado laboral.
¿Cuál es la diferencia entre la Composition API de Vue y los hooks de React?
Ambos agrupan la lógica con estado en funciones reutilizables. Un setup de Vue se ejecuta una vez por componente y sigue las dependencias automáticamente, así que no hay arrays de dependencias ni closures desactualizadas. Una función de componente de React se ejecuta en cada renderizado, así que los hooks deben llamarse siempre en el mismo orden y los efectos enumeran sus dependencias.
¿Vue usa JSX?
Vue admite JSX mediante un plugin, pero la mayor parte del código de Vue usa plantillas HTML en componentes de un solo archivo (archivos .vue). React usa JSX casi en todas partes.
¿Cuál es el equivalente de Next.js en Vue?
Nuxt. Igual que Next.js para React, agrega sobre Vue enrutamiento basado en archivos, renderizado en el servidor, generación estática y rutas de servidor.