React e Vue são ferramentas JavaScript para construir interfaces de usuário a partir de componentes (o React se chama de biblioteca, o Vue de framework progressivo), e compartilham a maior parte das ideias: props para baixo, eventos para cima, estado reativo, um virtual DOM. As diferenças práticas são que o React escreve a marcação em JSX e espera que o estado seja substituído com um setter, enquanto o Vue escreve a marcação em templates HTML dentro de single-file components e deixa você mudar os valores reativos diretamente. Aqui está um contador em React:
E o mesmo contador como single-file component do 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) vira ref(0), onClick vira @click e {count} vira {{ count }}. A diferença visível é o count++: o Vue deixa você mudar o valor no lugar, e o sistema de reatividade dele percebe. O React precisa do setCount porque só renderiza de novo quando você entrega um novo valor.
JSX vs single-file components
Um componente React é uma função JavaScript que retorna JSX. Condições são && ou um ternário, listas são .map(), e os estilos vêm do que você escolher (arquivos CSS, CSS modules, um framework de utilitários).
Um componente Vue normalmente é um arquivo .vue com três blocos: <script setup> para a lógica, <template> para a marcação e um <style scoped> opcional cujo CSS vale só para aquele componente. Os templates usam diretivas: v-if, v-for, v-model para binding de input em duas direções, :prop para ligar um valor e @event para ouvir. Os templates mantêm a marcação legível para quem conhece HTML; o JSX dá a você todo o JavaScript na marcação. O Vue também pode usar JSX e o React não pode usar templates, mas a maior parte do código em cada um segue o padrão.
Aqui está uma lista filtrada, a segunda funcionalidade para comparar.
Experimente digitar xyz para ver a mensagem de vazio e depois apague. A versão 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 substitui o par value mais onChange, e computed substitui a variável simples. No React, visible é recalculado em toda renderização porque a função do componente executa de novo; no Vue, computed o guarda em cache e só recalcula quando query muda. Os dois usam uma key para diferenciar os itens da lista.
O modelo de reatividade
Esta é a diferença mais profunda entre os dois.
React: estado imutável e re-renderizações. O estado é uma foto. Você chama um setter com um novo valor, o React executa de novo a função do componente, compara o novo JSX com o antigo e atualiza o DOM. O React compara valores com Object.is, então alterar um objeto ou array no lugar e passar o mesmo de volta parece não ter mudança nenhuma.
Clique em "push() in place" e nada muda na tela, porque o array é o mesmo objeto. Depois clique em "New array": a renderização também mostra pushed, porque a mutação anterior aconteceu de verdade, o React só não tinha motivo para olhar. A página do useState trata desse padrão a fundo.
Vue: valores reativos mutáveis. Uma ref ou um objeto reactive registra quem o lê (uma ref pelo getter .value, um objeto reactive por meio de um proxy). Quando você escreve nele, o Vue sabe exatamente quais valores computados, watchers e partes do template dependem dele e atualiza só esses. No Vue, items.value.push('pushed') atualiza a tela. Você escreve menos cerimônia e abre mão da garantia de que um valor nunca muda sem você saber.
Nenhum dos modelos é mais rápido de um jeito que importe para apps típicos. O React pode executar mais código de componente por mudança e depende de memoização (à mão ou pelo React Compiler) para pular trabalho; o Vue acompanha as dependências em tempo de execução, então pula esse trabalho por padrão.
Composition API vs hooks
A Composition API do Vue 3 e os hooks do React resolvem o mesmo problema: juntar estado e lógica relacionados e reutilizá-los entre componentes. O Vue chama as funções reutilizáveis de composables (useMouse()), o React as chama de hooks personalizados (useMouse()). As regras diferem por causa de quando o código executa.
- Quando executa. Um
setupdo Vue executa uma vez, quando o componente é criado. A função de um componente React executa em toda renderização, e os hooks dentro dela executam junto. - Regras de ordem. O React associa os hooks pela ordem das chamadas, então você não pode chamá-los dentro de condições ou loops. O Vue não tem essa regra para
refecomputed, porque o setup executa uma vez. - Dependências. Os efeitos e memos do React listam as dependências em um array que você mantém. O
watchEffecte ocomputeddo Vue acompanham automaticamente o que leem. - Valores desatualizados. Uma callback do React pode capturar um valor de estado antigo de uma renderização anterior (o clássico bug do
setInterval). Uma callback do Vue lêcount.valueno momento da chamada e sempre vê o valor atual.
O modelo do React faz de cada renderização uma função pura de props e estado, fácil de testar e de entender. O modelo do Vue elimina uma classe de bugs ligada aos arrays de dependências. Quem conhece um normalmente aprende o outro rápido.
Ecossistema
| React | Vue | |
|---|---|---|
| Marcação | JSX | Templates HTML em arquivos .vue (JSX opcional) |
| Atualizações de estado | Substituir com um setter, depois renderizar de novo | Mudar um valor reativo, os dependentes atualizam |
| Reuso de lógica | Hooks personalizados | Composables |
| Valores derivados | Calculados durante a renderização, useMemo | computed (em cache) |
| Binding de input em duas direções | value mais onChange | v-model |
| CSS com escopo | Não embutido (CSS modules, bibliotecas) | <style scoped> embutido |
| Roteamento | React Router, TanStack Router, frameworks | Vue Router (oficial) |
| Estado global | Context, Zustand, Redux Toolkit | Pinia (oficial) |
| Framework full-stack | Next.js, React Router no modo framework | Nuxt |
| Apps mobile | React Native | Sem opção oficial (Capacitor, NativeScript-Vue) |
| Ferramenta de build | Vite ou um framework | Vite |
| Mantido por | Meta e a comunidade | Uma equipe principal independente e a comunidade |
O padrão nessa tabela: a equipe principal do Vue mantém o roteador, a store e as devtools juntos, então um projeto Vue tem um padrão óbvio para cada um. O React deixa isso para a comunidade, o que dá mais opções e mais decisões. O Vite, a ferramenta de build usual para projetos novos nos dois, foi criado pelo criador do Vue.
Curva de aprendizado
O Vue costuma ser o começo mais suave. Os templates se leem como o HTML que você já conhece, o v-model elimina o código repetitivo dos inputs controlados, e um valor reativo atualiza a tela quando você o muda. O React pede o JSX e o hábito da atualização imutável logo de início, e a página sobre JSX é a primeira coisa de que a maioria das pessoas precisa.
Depois do básico, a diferença diminui. O Vue acrescenta os próprios conceitos (refs vs objetos reativos, .value nos scripts mas não nos templates, watchers), e o React acrescenta efeitos, memoização e as regras dos hooks. As vagas de emprego na sua região são um critério de desempate mais útil do que a sintaxe.
Quando escolher cada um
Escolha React quando:
- Você quer uma grande variedade de bibliotecas e componentes da comunidade, ou planeja construir apps mobile nativos com React Native.
- Você gosta de manter lógica e marcação em uma única função JavaScript e quer um framework como o Next.js.
- A sua equipe valoriza atualizações explícitas e imutáveis, que tornam cada renderização fácil de rastrear.
Escolha Vue quando:
- Você quer ferramentas oficiais e alinhadas para roteamento e estado, e menos decisões a tomar.
- A sua equipe inclui designers ou desenvolvedores back-end à vontade com templates HTML.
- Você está adicionando interatividade a páginas já renderizadas no servidor: o Vue pode ser colocado em uma página com uma tag script e crescer a partir dali.
Os dois são maduros e usados em produção por empresas de todos os tamanhos, e os conceitos que você aprende em um (componentes, props, estado derivado, listas com key) passam direto para o outro.
Perguntas frequentes
O Vue é mais fácil que o React?
Muitos iniciantes acham o Vue mais fácil no começo, porque os templates parecem HTML comum e mudar um valor reativo (count.value++) atualiza a tela sem setter. O React pede que você aprenda JSX e a regra de que o estado deve ser substituído, não alterado. Depois das primeiras semanas a dificuldade é parecida.
Qual é melhor, React ou Vue?
Nenhum ganha em geral. O React deixa roteamento e estado para bibliotecas da comunidade e tem o React Native para mobile. O Vue tem roteador, store e devtools oficiais mantidos juntos, e templates que muita gente acha mais fáceis de ler. Escolha o que a sua equipe ou o seu mercado de trabalho usa.
Qual é a diferença entre a Composition API do Vue e os hooks do React?
Os dois agrupam lógica com estado em funções reutilizáveis. Um setup do Vue executa uma vez por componente e acompanha as dependências automaticamente, então não há arrays de dependências nem closures desatualizadas. A função de um componente React executa em toda renderização, então os hooks precisam ser chamados na mesma ordem toda vez e os efeitos listam as dependências.
O Vue usa JSX?
O Vue suporta JSX por meio de um plugin, mas a maior parte do código Vue usa templates HTML em single-file components (arquivos .vue). O React usa JSX quase em todo lugar.
Qual é o equivalente do Next.js no Vue?
O Nuxt. Como o Next.js para o React, ele adiciona por cima do Vue roteamento baseado em arquivos, renderização no servidor, geração estática e rotas de servidor.