Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

The reactive function

reactive is the second way to declare state. It makes the object itself reactive, so its fields are accessed directly, without .value. It suits a group of related values, such as filter settings.

Declaring

<!-- src/App.vue -->
<script setup>
import { reactive } from 'vue'
 
const filter = reactive({
  query: '',
  onlyActive: false,
})
 
function toggle() {
  filter.onlyActive = !filter.onlyActive
}
</script>
 
<template>
  <button @click="toggle">
    {{ filter.onlyActive ? 'Show all' : 'Only active' }}
  </button>
</template>

Every click changes the button label. filter.onlyActive is changed in the script without .value, and Vue still re-renders the template.

Limits

reactive works only with objects, arrays, Map and Set. You cannot pass a string or a number — those need ref.

The second limit matters more: reactivity is lost if you replace the whole object or take it apart with destructuring.

<script setup>
import { reactive } from 'vue'
 
let filter = reactive({ query: '', onlyActive: false })
 
// The link is lost: the template still sees the old object
filter = reactive({ query: 'bread', onlyActive: true })
 
// query is a plain string, Vue will not see its changes
const { query } = filter
</script>

Destructuring from the tutorial's objects lesson copies the values into plain variables here, and they stop being reactive.

Comparison

refreactive
TypesAnyObjects and collections only
Access in scriptcount.valuefilter.query
Replacing entirelytodos.value = []Not possible
DestructuringNot neededBreaks reactivity

Which to choose

The Vue documentation recommends ref by default: it works with any value, it can be replaced entirely, for example with data from an API, and .value in the code shows at once where a reactive variable is. The rest of the course uses ref. reactive is handy for small grouped objects such as a form that is never replaced as a whole.

<script setup>
import { ref } from 'vue'
 
const filter = ref({ query: '', onlyActive: false })
 
function reset() {
  filter.value = { query: '', onlyActive: false }
}
</script>

With ref, resetting to the initial values is a single assignment.

Common mistake

Loading data and assigning it to a reactive variable:

<script setup>
import { reactive } from 'vue'
 
let todos = reactive([])
 
async function load() {
  const response = await fetch('/todos.json')
  todos = await response.json() // The list on the page does not update
}
</script>

Declare the list with ref([]) and write todos.value = await response.json() — then the new array reference is noticed.

Thanks for reading!

Donate to the site — we work hard for you.