Lesson 4 / 25

ref and reactive

The two ways to declare reactive state.

Wrapping values so Vue can track them

ref(value) wraps any value (including primitives) in an object with a .value property; reading .value is tracked and writing it triggers updates. In templates, top-level refs are unwrapped automatically, so you write {{ count }} rather than {{ count.value }}. reactive(object) returns a deeply reactive Proxy of an object, array, Map or Set, with no .value. reactive has limits: it cannot hold primitives, replacing the whole object breaks the connection, and destructuring its properties into local variables loses reactivity. For these reasons the Vue docs recommend ref as the primary API.

State that updates the UI

Vue tracks reads of reactive state during rendering and re-runs the affected work when that state changes.

Three ideas: ref and reactive, computed values, watchers.
Figure 2.1 — Reactive state, derived values and side effects.

ref and reactive side by side

Note where .value is needed.

<script setup>
import { ref, reactive } from 'vue'

const count = ref(0)
const user = reactive({ name: 'Asha', tags: ['admin'] })

function increment() {
  count.value++            // .value in script
  user.tags.push('active') // deep reactivity, no .value
}

// const { name } = user  // loses reactivity: name is a plain string
</script>

<template>
  <!-- refs are unwrapped in the template -->
  <p>{{ user.name }} has clicked {{ count }} times</p>
  <button @click="increment">+1</button>
</template>

A box with a sensor

A ref is a box with a sensor on the lid: Vue notices whenever someone opens it (reads .value) or puts something new inside (writes .value).

Quick check: Why does destructuring a reactive() object into local variables cause problems?

  • It throws a runtime error
  • The local variables are plain values and are no longer reactive
  • It deep-copies the whole store
  • It makes the object read-only
Answer

The local variables are plain values and are no longer reactive — Reactivity lives on the Proxy, not on copied values; toRefs can help.