Understanding Reactivity
Reactivity is the mechanism that makes Vue update the DOM when data changes. It’s not magic — it’s a precise system with defined rules. Understanding those rules helps you avoid the most common Vue bugs.
The problem with plain variables
Section titled “The problem with plain variables”<script setup lang="ts">let count = 0 // plain variable
function increment() { count++ // changes the variable, but Vue doesn't know}</script>
<template> <p>{{ count }}</p> <button @click="increment">+1</button></template>Click the button — count increases in memory, but the paragraph never updates. Vue has no way to know the variable changed.
How Vue tracks changes
Section titled “How Vue tracks changes”Vue uses JavaScript Proxies to wrap reactive state. When you read a reactive property, Vue registers a dependency: “this template depends on this value.” When you write to it, Vue knows to re-run any template or computed that depended on it.
Read reactive value → Vue notes the dependencyWrite reactive value → Vue re-renders dependentsThis happens automatically. You don’t call setState, dispatch an action, or manually trigger updates. You just mutate the reactive value and Vue handles the rest.
What makes state reactive
Section titled “What makes state reactive”Only values created with Vue’s reactivity APIs are reactive:
ref(value)— wraps any value in a reactive referencereactive(object)— makes an entire object deeply reactivecomputed(() => ...)— a derived reactive value
Plain let variables, const objects, and function arguments are not reactive. Changing them won’t trigger re-renders.
A reactive counter
Section titled “A reactive counter”<script setup lang="ts">import { ref } from 'vue'
const count = ref(0) // ✅ reactive
function increment() { count.value++ // Vue detects this and re-renders}</script>
<template> <p>{{ count }}</p> <button @click="increment">+1</button></template>Now the paragraph updates when the button is clicked. count is a reactive ref — Vue tracks reads of count.value in the template and re-renders when it changes.
Reactivity is automatic and efficient
Section titled “Reactivity is automatic and efficient”Vue only re-renders components that actually depend on changed data. If PersonCard renders name and birthYear, only PersonCard re-renders when name changes — not the entire tree.
This is why Vue apps feel fast even with large component trees. Reactivity is surgical, not broad.
Exercise
Section titled “Exercise”- Create a new component
ReactivityDemo.vue. - Add a plain
let count = 0and a button that increments it. Confirm it doesn’t update in the browser. - Change it to
const count = ref(0). Confirm the browser now updates. - Add a second variable
const message = ref('hello')and a button that changes it to'world'. Confirm both values update independently.
- Vue tracks reactive state with Proxies — reads register dependencies, writes trigger re-renders.
- Plain
let/constvariables are not reactive — changes don’t update the DOM. ref(),reactive(), andcomputed()create reactive state.- Vue only re-renders components that depend on the changed value — not the entire tree.