Vue’s reactivity system tracks data dependencies and updates only the affected DOM bindings, reducing manual state wiring. Compared to React’s explicit state updates and reconciliation, Vue offers automatic dependency tracking with template-level reactivity.
What problems does Vue’s reactivity system solve, and how does Vue differ from React conceptually?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
What Vue reactivity solves (the practical problems)
In UI code you constantly fight the same issues: keeping DOM in sync with state, updating derived values efficiently, and avoiding “update everything” work. Vue’s reactivity system solves these by automatically tracking what your UI depends on and updating only what’s affected when state changes.
Problem in UI apps | Without reactivity you do... | Vue reactivity gives you... |
|---|---|---|
State → DOM synchronization | Manually set text/classes/attributes or write glue code everywhere | Declarative templates; mutate state and the DOM updates automatically |
Derived state (filters, totals, formatting) | Recompute on every render or cache manually | computed() is cached automatically and invalidated only when dependencies change |
Avoiding unnecessary work | Re-render or recompute too much, then add manual memoization | Dependency tracking updates only the effects/components that actually touched the changed property |
Batching multiple changes | Accidentally trigger multiple paints/renders in a row | Updates are queued/deduped and flushed (microtask) so many mutations typically produce one DOM patch |
Side effects based on state changes | Wire custom subscriptions and cleanup | watch()/watchEffect() run when tracked dependencies change, with controlled timing (flush options) |
What Vue is doing under the hood (high level)
Vue 3 wraps state in Proxies. When code runs inside a reactive “effect” (component render, computed, watcher), any reactive get is tracked. When you later set a reactive property, Vue triggers only the effects that previously read that property. Those effects are scheduled and batched, then Vue patches the DOM.
<!-- Vue 3 (Composition API) - fine-grained dependency tracking -->
<script setup>
import { ref, computed } from 'vue';
const price = ref(100);
const qty = ref(2);
// Cached until price/qty changes
const total = computed(() => price.value * qty.value);
function addOne() {
qty.value++;
}
</script>
<template>
<p>Qty: {{ qty }}</p>
<p>Total: {{ total }}</p>
<button @click="addOne">+1</button>
</template>
How Vue differs from React conceptually
The biggest difference is the update model:
• Vue: “push” model. Dependency graph decides what to update (who depends on what). Component updates happen because reactive reads were tracked.
• React: “render-as-a-function” model. State updates schedule a re-render of a component; during re-render React re-executes your component function to compute the next UI, then reconciles.
Aspect | Vue (conceptual model) | React (conceptual model) |
|---|---|---|
Update trigger | Reactive property write triggers tracked dependents (effects/components) | setState/useState setter schedules component re-render |
Granularity | Property-level dependency tracking; avoids updating unrelated dependents | Component-level re-render by default; you add memoization/selectors to skip work |
Authoring UI | Templates (compiled) + directives; JS in script section (SFC) | JSX/TSX (UI is JS); everything expressed as functions/components |
Optimization story | Compiler hints (patch flags/block tree) + reactive tracking reduce diffing work | Reconciliation + memo/useMemo/useCallback + architecture patterns reduce re-render cost |
Derived state | computed() is first-class and cached by default | Derived values computed during render; caching is manual (useMemo) or via external stores |
Two-way binding | Built-in pattern ( | Explicit: value + onChange (controlled components) or uncontrolled refs |
Mental model summary | Mutate reactive state; Vue figures out what depends on it | Update state; React re-runs render to recompute UI |
// React - re-render computes next UI
import { useMemo, useState } from 'react';
export function Cart() {
const [price, setPrice] = useState(100);
const [qty, setQty] = useState(2);
// Optional caching (manual)
const total = useMemo(() => price * qty, [price, qty]);
return (
<>
<p>Qty: {qty}</p>
<p>Total: {total}</p>
<button onClick={() => setQty(q => q + 1)}>+1</button>
</>
);
}
Interview-ready takeaway
Vue’s reactivity exists to remove manual DOM sync and to make updates precise via dependency tracking + batching. React’s core idea is re-running component functions to describe the next UI and reconciling the result. Vue leans on a reactive graph + compiler; React leans on a render cycle + reconciliation, with optimization patterns layered on top.