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 placereactive 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 updatesreactive 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 needref. - Do not replace it.
filters = reactive({...})(withlet) gives a brand-new proxy; the template still watches the old one. - Do not destructure it.
const { genre } = filterscopies 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.
The code
const filters = reactive({ genre: 'all' }), thenconst { genre } = filters, and the template shows{{ genre }}.
Drills
Answer fast — trust the rule.
const count = ref(0). How do you add 1 in script code?
Which call does NOT give you reactive state?
const { hideFinished } = filters where filters is reactive. Later filters.hideFinished = true. What does hideFinished hold?
Which statement about ref is true?
Remember
refwraps any value and is read through.value;reactivemakes an object reactive with no.value.- Shortcut: "am I still touching the tracked thing?"
.valuefor refs, the original proxy for reactive. - Trap: destructuring or replacing a reactive object breaks the link. Prefer
refby default.
