Quick Answer

ref replaces useState, computed replaces useMemo, watchEffect replaces useEffect. The main difference is that Vue tracks dependencies automatically and re-renders only what changed, so there is no dependency array and no memoisation ceremony.

A component side by side

A counter in React:

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

The same in Vue, using the Composition API with <script setup>:

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

Two structural differences. Vue separates template from logic rather than mixing them in JSX. And there is no setter — you assign to count.value directly, or in the template just count, because Vue unwraps refs there.

The .value is the thing React developers trip over. Inside <script> you write count.value++; inside <template> you write count. Forgetting .value in script code is the most common Vue beginner bug, and it fails silently rather than erroring.

Reactivity: the real difference

React re-runs the whole component function on every state change and relies on you to memoise what should not be recomputed. Vue tracks which values each piece of the template actually read, and updates only those.

The practical consequences:

const doubled = computed(() => count.value * 2)

That is useMemo with no dependency array. Vue knows doubled read count, so it recomputes when and only when count changes. Nothing to forget, nothing to get stale.

The same applies to effects:

watchEffect(() => {
  console.log('count is', count.value)
})

No dependency array either. Vue does not have the class of bug where a missing dependency gives you a stale closure — which is a meaningful share of React debugging.

There is no useCallback or React.memo equivalent needed, because Vue does not re-run the component on every change in the first place.

Template syntax instead of JSX

<template>
  <p v-if="loading">Loading...</p>
  <ul v-else>
    <li v-for="s in students" :key="s.id">{{ s.name }}</li>
  </ul>

  <input v-model="query">
</template>

Where React uses JavaScript — ternaries and .map() — Vue uses directives. v-if for conditionals, v-for for lists, :prop to bind an attribute, @event to listen.

v-model has no direct React equivalent. It is two-way binding: the input updates query and query updates the input, replacing the value-plus-onChange pair React requires for every field. On a large form that is a noticeable reduction in code.

The trade-off is familiar from the framework debates: JSX is just JavaScript, so anything you can express in code you can express in a template. Vue's directives cover the common cases more concisely and require learning a small syntax.

Props and events

<script setup>
const props = defineProps({ student: Object })
const emit = defineEmits(['select'])
</script>

<template>
  <button @click="emit('select', props.student.id)">
    {{ props.student.name }}
  </button>
</template>

Props work as in React. The difference is events: rather than passing a callback prop, a Vue child emits a named event the parent listens for with @select="handler".

Functionally equivalent, and the declaration is more explicit — defineEmits documents exactly what a component can emit, where a React component's callback props are just props you have to notice.

Props are one-way in both frameworks. Mutating a prop in Vue produces a warning, same as React's convention.

Ecosystem and when to pick it

Vue's ecosystem is more official. Routing is Vue Router, state is Pinia, the meta-framework is Nuxt — all maintained by the core team. React leaves these to the community, which gives more choice and more decisions.

For a student, that is a genuine advantage: fewer decisions, more consistent documentation, and tutorials that agree with each other.

Practical considerations for choosing:

  • Job market. React dominates listings in India and globally. If employability is the goal, learn React first — this is the decisive factor for most students.
  • Learning curve. Vue is generally easier to start with, particularly if you know HTML and CSS well but are shakier on JavaScript.
  • Existing codebase. Usually decided for you.

The concepts transfer almost entirely — components, props, reactive state, derived values, effects, lifecycle. Learning the second framework properly takes days, not months, which is worth saying because the framework wars imply otherwise.

Frequently Asked Questions

What is the Vue equivalent of useState? ref() for individual values and reactive() for objects. Read and write ref values with .value in script code; templates unwrap them automatically.
Why does Vue not need a dependency array? It tracks which reactive values each computation reads and re-runs only when those change. That removes the stale-closure bugs caused by missing React dependencies.
What is v-model? Two-way binding between an input and a variable, replacing React's value plus onChange pair. It noticeably reduces boilerplate on forms.
Should I learn React or Vue first? React, if employability is the goal — it dominates job listings. Vue is easier to learn and the concepts transfer, so picking up the second one later takes days.
Is Vue slower than React? No. Vue's fine-grained reactivity often means less work per update, since it does not re-run whole components. For real applications both are fast enough that architecture matters more.