Vue 3 Reactivity API Explained with Examples
When you build app in vue Vue.js, you can see the UI automatically updated when there is change on the code. This mechanisms refer to reactive API, it the set of tools and functions provided by Vue for the UI to automatically update in response to changes in underlying data.
Vue 3 introduces a powerful new feature Composition API, and at its core lies the Reactivity API. It tools that let you declare reactive variables and track changes in a fine-grained way.
In this article, we’ll cover the most important Reactivity APIs:
ref()
reactive()
computed()
watch()
watchEffect()
readonly()
toRef() and toRefs()
1.ref(): Reactive Primitive Values
The ref function wraps a value in a reactive reference, which can be updated and tracked.
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
Use .value to access the actual value inside a ref (except in <template>).
Suitable for numbers, strings, booleans, etc.
2.reactive(): Reactive Objects and Arrays
The reactive function creates a reactive proxy of an object or array.
<script setup>
import { reactive } from 'vue'
const user = reactive({
name: 'Nova',
age: 28
})
</script>
<template>
<div>
<p>{{ user.name }} is {{ user.age }} years old</p>
</div>
</template>
Automatically tracks nested properties.
Ideal for managing structured state (objects, arrays).
3. computed(): Derived Reactive Values
computed creates a reactive value based on other reactive data. It automatically updates when its dependencies change.
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('Nova')
const lastName = ref('Dev')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
</script>
<template>
<div>
<p>Full Name: {{ fullName }}</p>
</div>
</template>
Useful for getters or derived values.
4.watch(): Responding to Reactive Changes
watch allows you to perform side effects when a reactive value changes.
<script setup>
import { ref, watch } from 'vue'
const age = ref(20)
watch(age, (newVal, oldVal) => {
console.log(`Age changed from ${oldVal} to ${newVal}`)
})
</script>
<template>
<div>
<input type="number" v-model="age" />
<p>Your age: {{ age }}</p>
</div>
</template>
Great for validating input, fetching data, logging, etc.
5.watchEffect(): Automatically Tracks Dependencies
watchEffect runs immediately and automatically tracks any reactive dependency used inside its function.
<script setup>
import { ref, watchEffect } from 'vue'
const name = ref('Nova')
watchEffect(() => {
console.log(`The name is: ${name.value}`)
})
</script>
<template>
<div>
<input v-model="name" />
<p>Hello, {{ name }}!</p>
</div>
</template>
Simpler than watch for many cases.
Automatically collects dependencies used inside its callback.
6.readonly(): Make State Read-Only
readonly makes a reactive object immutable from the outside.
<script setup>
import { reactive, readonly } from 'vue'
const state = reactive({ count: 0 })
const readOnlyState = readonly(state)
</script>
<template>
<div>
<p>{{ readOnlyState.count }}</p>
</div>
</template>
Attempts to mutate readOnlyState.count will be ignored (in dev, they throw a warning).
Useful for exposing state safely to components.
7.toRef() and toRefs(): Extract Individual Refs
These are useful when destructuring reactive objects.
<script setup>
import { reactive, toRefs } from 'vue'
const user = reactive({
name: 'Nova',
age: 30
})
const { name, age } = toRefs(user)
</script>
<template>
<div>
<p>{{ name }} is {{ age }} years old</p>
</div>
</template>
toRefs() returns an object with each property converted into a ref.
Maintains reactivity even when destructured.
Let’s try it Online
You can test all of the examples above using the official Vue SFC Playground:
https://sfc.vuejs.org
Just copy any of the code examples into the editor and run it.
Vue 3’s Reactivity API gives you full control over your application’s state. Use ref for primitives, reactive for objects, and combine them with computed, watch, and watchEffect for flexible and powerful reactivity handling.

