What you'll learn
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.
