SyntaxStudy
Sign Up
Vue.js ref and reactive Fundamentals
Vue.js Beginner 1 min read

ref and reactive Fundamentals

Vue 3's reactivity system is built on ES Proxy objects. The two primary APIs are `ref` and `reactive`. `ref` wraps any value — primitive or object — in a reactive container. Inside JavaScript you access or mutate the value through the `.value` property; inside templates Vue automatically unwraps refs so you write `{{ count }}` rather than `{{ count.value }}`. `reactive` accepts an object (or array) and returns a deeply reactive Proxy of it. Property access and mutation are tracked directly without a `.value` wrapper, making it feel more natural for complex state objects. However, `reactive` has a key limitation: destructuring it or replacing the whole object breaks reactivity because the Proxy reference is lost. For that reason, many developers prefer `ref` exclusively and simply do `ref({ name: '', email: '' })` when they need an object. When you must destructure a `reactive` object use `toRefs()`, which converts each property into a standalone `ref` linked to the original.
Example
<script setup>
import { ref, reactive, toRefs, watchEffect } from 'vue';

// ── ref ──────────────────────────────────────
const count   = ref(0);
const message = ref('Hello');
count.value++;                    // mutate via .value
console.log(count.value);         // 1

// ── reactive ─────────────────────────────────
const state = reactive({ name: 'Alice', age: 30 });
state.age++;                      // no .value needed
console.log(state.name, state.age);

// ── toRefs: safe destructure ──────────────────
const { name, age } = toRefs(state);
name.value = 'Bob';               // still linked to state

// ── watchEffect: auto-tracks dependencies ─────
watchEffect(() => {
  console.log('count is now', count.value);
  console.log('name is now',  name.value);
});

// ── Reactive array ─────────────────────────────
const items = ref([]);
items.value.push({ id: 1, label: 'First' });
</script>
<template>
  <p>{{ count }} — {{ state.name }}</p>
</template>