Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
API Styles  ›  Lesson

ref and reactive

Composition API 14 minref wraps any value in a reactive box read through .value, while reactive makes an object itself reactive but breaks when replaced or destructured.

ref and reactive

Shelf needs filter state: which genre to show and whether to hide finished books. You could store it as two refs or as one reactive object. Both work, until someone destructures the object or replaces it wholesale and the page silently stops updating. Knowing how each tool tracks changes prevents that.

The rule

ref boxes any value in .value; reactive wraps an object, so keep the wrapper.

ref wraps any value, a number, a string, an array or an object, in a small box. You read and write through .value, and Vue notices every write:

import { ref, reactive } from 'vue'

const genre = ref('all')
genre.value = 'science'           // page updates

const books = ref([])
books.value = [{ title: 'Dune' }]  // replacing the whole array is fine
books.value.push({ title: 'Circe' }) // so is changing it in place

reactive takes an object and returns a proxy: a stand-in that notices whenever its properties are read or written. No .value:

const filters = reactive({ genre: 'all', hideFinished: false })
filters.genre = 'science'         // page updates

reactive has three limits, all from the same cause, which is that Vue tracks the proxy itself:

  • Objects only. reactive('all') does not work; strings, numbers and booleans need ref.
  • Do not replace it. filters = reactive({...}) (with let) gives a brand-new proxy; the template still watches the old one.
  • Do not destructure it. const { genre } = filters copies the current string into a plain variable that Vue does not track. If you need separate pieces, toRefs(filters) gives refs linked to each property.

In templates, top-level refs are unwrapped, so {{ genre }} works. Because ref has none of reactive's limits, the Vue docs suggest ref as the default choice.

The shortcut

When a value will not update, ask: "Am I still touching the tracked thing?" For a ref, that means going through .value. For reactive, that means going through the original proxy.

Why the genre label frozeStep 1 of 4
  1. The code

    const filters = reactive({ genre: 'all' }), then const { genre } = filters, and the template shows {{ genre }}.

Drills

Answer fast — trust the rule.

quick drill

const count = ref(0). How do you add 1 in script code?

quick drill

Which call does NOT give you reactive state?

quick drill

const { hideFinished } = filters where filters is reactive. Later filters.hideFinished = true. What does hideFinished hold?

quick drill

Which statement about ref is true?

Remember

  • ref wraps any value and is read through .value; reactive makes an object reactive with no .value.
  • Shortcut: "am I still touching the tracked thing?" .value for refs, the original proxy for reactive.
  • Trap: destructuring or replacing a reactive object breaks the link. Prefer ref by default.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhere did reactivity go?

A teammate writes const filters = reactive({ genre: 'all' }), then later const { genre } = filters and uses genre in the template. Changing filters.genre no longer updates the page. Explain why and give two fixes.