Skip to main content

Reactivity API: Utilities

Utility functions for inspecting and working with reactive state.

isRef()

Checks if a value is a ref object.
value
unknown
required
The value to check.
Type:
function isRef<T>(r: Ref<T> | unknown): r is Ref<T>
Returns: boolean - true if the value is a ref, false otherwise Example:
import { ref, isRef } from 'vue'

const count = ref(0)
const plain = 0

console.log(isRef(count)) // true
console.log(isRef(plain)) // false
Details:
  • Returns true for refs created by ref(), shallowRef(), computed(), or customRef()
  • Type guard function that narrows the type to Ref<T>

unref()

Returns the inner value if the argument is a ref, otherwise returns the argument itself. This is a sugar function for val = isRef(val) ? val.value : val.
ref
MaybeRef<T> | ComputedRef<T>
required
A ref or plain value to be converted into the plain value.
Type:
function unref<T>(ref: MaybeRef<T> | ComputedRef<T>): T

type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>
Returns: T - The unwrapped value Example:
import { ref, unref } from 'vue'

function useFoo(x: number | Ref<number>) {
  const unwrapped = unref(x)
  // unwrapped is guaranteed to be a number
  return unwrapped * 2
}

useFoo(1) // 2
useFoo(ref(1)) // 2
Details:
  • Useful for writing functions that accept both refs and plain values
  • If the value is a ref, returns .value
  • If the value is not a ref, returns the value as-is

toRef()

Used to normalize values / refs / getters into refs. Can also be used to create a ref for a property on a source reactive object.
source
T | object
A getter function, an existing ref, a non-function value, or a reactive object.
key
K extends keyof T
(Optional) The name of the property in the reactive object.
defaultValue
T[K]
(Optional) Default value to use if the property is undefined.
Type:
// Normalize value/ref/getter to ref
function toRef<T>(
  value: T
): T extends () => infer R
  ? Readonly<Ref<R>>
  : T extends Ref
    ? T
    : Ref<UnwrapRef<T>>

// Create ref from reactive object property
function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K
): ToRef<T[K]>

function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K,
  defaultValue: T[K]
): ToRef<Exclude<T[K], undefined>>
Returns: Ref<T> - A ref object Example:
import { reactive, toRef } from 'vue'

// returns existing refs as-is
const existingRef = ref(1)
toRef(existingRef) // returns existingRef

// creates a ref that calls the getter on .value access
toRef(() => props.foo)

// creates normal refs from non-function values
toRef(1) // equivalent to ref(1)
Property refs:
const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

// mutating the ref updates the original
fooRef.value++
console.log(state.foo) // 2

// mutating the original also updates the ref
state.foo++
console.log(fooRef.value) // 3
Details:
  • Can normalize a value, ref, or getter function into a ref
  • When passed a reactive object and key, creates a ref that stays in sync with the object’s property
  • The created ref is synced with its source property: mutating the source property updates the ref, and vice-versa
  • Useful for passing a single property of a reactive object to a composable while preserving reactivity
See also:

toRefs()

Converts a reactive object to a plain object where each property of the resulting object is a ref pointing to the corresponding property of the original object. Each individual ref is created using toRef().
object
T extends object
required
A reactive object to be converted into an object of refs.
Type:
function toRefs<T extends object>(object: T): ToRefs<T>

type ToRefs<T = any> = {
  [K in keyof T]: ToRef<T[K]>
}
Returns: ToRefs<T> - A plain object with ref properties Example:
import { reactive, toRefs } from 'vue'

const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)

// The ref and the original property are "linked"
state.foo++
console.log(stateAsRefs.foo.value) // 2

stateAsRefs.foo.value++
console.log(state.foo) // 3
Useful when returning from composables:
function useFeature() {
  const state = reactive({
    foo: 1,
    bar: 2
  })

  // return refs when returning
  return toRefs(state)
}

// can destructure without losing reactivity
const { foo, bar } = useFeature()
Details:
  • Useful when returning a reactive object from a composition function
  • Allows consuming components to destructure/spread the returned object without losing reactivity
  • Only converts enumerable properties on the source object
  • Each ref stays in sync with the corresponding property on the source object
See also:

isProxy()

Checks if an object is a proxy created by reactive(), readonly(), shallowReactive(), or shallowReadonly().
value
any
required
The value to check.
Type:
function isProxy(value: any): boolean
Returns: boolean - true if the value is a Vue reactive proxy, false otherwise Example:
import { reactive, readonly, isProxy } from 'vue'

const state = reactive({ count: 0 })
console.log(isProxy(state)) // true

const readonlyState = readonly(state)
console.log(isProxy(readonlyState)) // true

const plain = { count: 0 }
console.log(isProxy(plain)) // false

isReactive()

Checks if an object is a proxy created by reactive() or shallowReactive().
value
unknown
required
The value to check.
Type:
function isReactive(value: unknown): boolean
Returns: boolean - true if the value is a reactive proxy, false otherwise Example:
import { reactive, readonly, isReactive, ref } from 'vue'

isReactive(reactive({}))            // true
isReactive(readonly(reactive({})))  // true
isReactive(ref({}).value)           // true
isReactive(readonly(ref({})).value) // true
isReactive(ref(true))               // false
isReactive(shallowRef({}).value)    // false
isReactive(shallowReactive({}))     // true
Details:
  • Returns true even if the proxy is created by readonly(), but wraps a reactive proxy created by reactive()
  • Also returns true for proxies created by shallowReactive()

isReadonly()

Checks whether the passed value is a readonly object. The properties of a readonly object can change, but they can’t be assigned directly via the passed object.
value
unknown
required
The value to check.
Type:
function isReadonly(value: unknown): boolean
Returns: boolean - true if the value is readonly, false otherwise Example:
import { readonly, isReadonly, computed } from 'vue'

const original = { count: 0 }
const wrapped = readonly(original)

console.log(isReadonly(wrapped)) // true
console.log(isReadonly(original)) // false

// computed refs without a setter are readonly
const computedRef = computed(() => 1)
console.log(isReadonly(computedRef)) // true
Details:
  • The proxies created by readonly() and shallowReadonly() are both considered readonly
  • A computed ref without a set function is also considered readonly

toRaw()

Returns the raw, original object of a Vue-created proxy.
observed
T
required
The proxy object for which the raw value is requested.
Type:
function toRaw<T>(observed: T): T
Returns: T - The original, non-proxy object Example:
import { reactive, toRaw } from 'vue'

const foo = {}
const reactiveFoo = reactive(foo)

console.log(toRaw(reactiveFoo) === foo) // true
Details:
  • toRaw() can return the original object from proxies created by reactive(), readonly(), shallowReactive(), or shallowReadonly()
  • This is an escape hatch that can be used to temporarily read without incurring proxy access/tracking overhead or write without triggering changes
  • It is not recommended to hold a persistent reference to the original object. Use with caution
See also:

markRaw()

Marks an object so that it will never be converted to a proxy. Returns the object itself.
value
T extends object
required
The object to be marked as “raw”.
Type:
function markRaw<T extends object>(value: T): Raw<T>

type Raw<T> = T & { [RawSymbol]?: true }
Returns: Raw<T> - The same object, marked to never be made reactive Example:
import { reactive, markRaw, isReactive } from 'vue'

const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false

// also works when nested inside other reactive objects
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
Use cases:
// External library objects that should not be made reactive
const map = markRaw(new google.maps.Map(element, options))

// Objects with complex internal state that would be expensive to track
const hugeList = markRaw([
  /* thousands of items */
])
Details:
  • Useful for values that should never be made reactive, such as complex third-party class instances or Vue component objects
  • Used together with shallow APIs like shallowReactive() to selectively opt-out of deep reactive/readonly conversion
  • Allows embedding raw, non-proxied objects in your state graph
Warning:
  • markRaw() and shallow APIs allow you to selectively opt-out of the default deep reactive/readonly conversion and embed raw, non-proxied objects in your state graph
  • However, they can be tricky to use. Consider flattening your data structure to avoid the need for them
See also:

toReactive()

Returns a reactive proxy of the object. If the value is already reactive, it is returned as-is.
object
T extends object
required
The object to convert to a reactive proxy.
Type:
function toReactive<T>(value: T): UnwrapNestedRefs<T>
Returns: UnwrapNestedRefs<T> - A reactive proxy of the object, or the value as-is if not an object Example:
import { toReactive, isReactive } from 'vue'

const obj = { count: 0 }
const reactiveObj = toReactive(obj)
console.log(isReactive(reactiveObj)) // true

// If already reactive, returns as-is
const existing = reactive({ count: 0 })
console.log(toReactive(existing) === existing) // true

// Non-objects are returned as-is
console.log(toReactive(1)) // 1
console.log(toReactive('hello')) // 'hello'
Details:
  • This is a convenience method for normalizing values to reactive proxies
  • If the input is already reactive, it returns the same reference
  • If the input is not an object (primitives), it returns the value unchanged
  • Internally converts the object using reactive() if not already reactive

toReadonly()

Returns a readonly proxy of the object. If the value is already readonly, it is returned as-is.
object
T extends object
required
The object to convert to a readonly proxy.
Type:
function toReadonly<T>(value: T): DeepReadonly<UnwrapNestedRefs<T>>
Returns: DeepReadonly<UnwrapNestedRefs<T>> - A readonly proxy of the object, or the value as-is if not an object Example:
import { toReadonly, isReadonly } from 'vue'

const obj = { count: 0 }
const readonlyObj = toReadonly(obj)
console.log(isReadonly(readonlyObj)) // true

// If already readonly, returns as-is
const existing = readonly({ count: 0 })
console.log(toReadonly(existing) === existing) // true

// Non-objects are returned as-is
console.log(toReadonly(1)) // 1
console.log(toReadonly('hello')) // 'hello'
Details:
  • This is a convenience method for normalizing values to readonly proxies
  • If the input is already readonly, it returns the same reference
  • If the input is not an object (primitives), it returns the value unchanged
  • Internally converts the object using readonly() if not already readonly

Build docs developers (and LLMs) love