I have just started working with Vue 3 and the Composition API.
What are the differences between ref
, toRef
and toRefs
?
ref
A ref is a mechanism for reactivity in Vue 3. The idea is to wrap a non-object variable inside a reactive
object:
Takes an inner value and returns a reactive and mutable ref object. The ref object has a single property
.value
that points to the inner value.
Hmm.. Why?
Vue 3 relies on JavaScript proxies to detect changes to your reactive data and implement the reactivity. Proxies are essentially event listeners for objects: any reading or writing on a proxied object triggers the proxy, which can then do something with the values. This is convenient for reactivity since the variable changing will provide a trigger from which Vue can update any dependencies.
But proxies require objects to work. So Vue provides the ref
method to convert your non-object variables into objects and then to grant reactive capabilities through a proxy. (Objects are reference variables, hence the name ref
.)
(And Vue automatically unwraps your refs
in the template, which is an added benefit of ref
that you wouldn't get if you wrapped your value variables in an object manually.)
reactive
If your original variable is already an object (or array), a ref
wrapping is not *usually needed because it is already a reference type. It only needs Vue's reactive functionality (which a ref
also has):
const state = reactive({
foo: 1,
bar: 2
})
But now consider copying a property from the object above to a new variable, for example foo
which contains the number 1
. If you copied this to a new variable, the copy would of course be a regular, non-reactive variable having no connection to the reactive object it was copied from. If foo
changed later, the copy would not, meaning the copy is not reactive. This is where toRef
is useful.
toRef
toRef
converts a single reactive
object property to a ref
that maintains its connection with the parent object:
const state = reactive({ foo: 1, bar: 2 }) const fooRef = toRef(state, 'foo') /* fooRef: Ref<number>, */
Now if state.foo
changes, fooRef.value
will change as well. So toRef
has enabled copying a value property in such a way that the copy also has a reactive connection to the original parent object.
toRefs
toRefs
converts all of the object's properties, to a new plain object having properties that are refs:
const state = reactive({ foo: 1, bar: 2 }) const stateAsRefs = toRefs(state) /* { foo: Ref<number>, bar: Ref<number> } */
When would I ever use toRef
or toRefs
?
The most likely time would be when importing a reactive object that has value properties like the example, such as from a composable, and destructuring it. The act of destructuring will pull the current property value from the object into a new local variable that will not be reactive without toRef
. You may notice this when importing and destructuring a Pinia store into your component, for example.
* Sometimes a ref
is useful even on objects/arrays. For example, if you want to declare a variable to be set later by an async result