Vue 3 Composition API: ref() vs. reactive()
One of the first questions that arise when starting with the new Vue Composition API is ref()
or reactive()
? The initial instinct is to use ref()
for primitives (Boolean, String,…) and reactive()
for objects. But there is more to it.
- When to Use
ref()
and When to Usereactive()
? - The Downside of Using
ref()
- Is Mixing
ref()
andreactive()
a Good Idea?
When to Use ref()
and When to Use reactive()
?
Let’s start with the basics: you must use ref()
to create a reactive primitive value.
// Boolean ref
const isVisible = ref(true);
// String ref
const name = ref("Markus");
reactive()
, on the other hand, can only be used for creating reactive objects. You can use it as a replacement for the old data
option in standard Option API-based Vue components, for example.
const state = reactive({
isVisible: true,
name: "Markus",
});
But you can also use ref()
for that. In the following example, we use ref()
to create a reactive object.
const state = ref({
isVisible: true,
name: "Markus",
});
There are two notable differences when using ref()
instead of reactive()
for objects. The first one is more of a downside, but I consider the second one a significant advantage.
const state = ref({
isVisible: true,
name: "Markus",
});
// 1. You must use `.value` to access properties
// of a `ref()` object. With `reactive()` you
// could do `state.isVisible = false`.
state.value.isVisible = false;
// 2. You can swap the complete object. You can't
// do that with `reactive()` objects!
state.value = {
isVisible: false,
name: "John",
};
The Downside of Using ref()
Constantly having to use .value
when working with refs is a bummer. But at least it makes it very clear that you’re working with reactive data.
One possible workaround, especially when dealing with data that might or might not be a ref, is to use unref()
.
import { unref } from "vue";
// `number` might or might not be a ref.
function addOne(number) {
return unref(number) + 1;
}
Is Mixing ref()
and reactive()
a Good Idea?
Because I think sometimes having to use .value
and sometimes not is confusing, I tend not to use reactive()
at all.
Yes, always having to deal with .value
even if I could avoid it sometimes by using reactive()
is annoying. But the magic word here is sometimes. ref()
can be used for every occasion, reactive()
can’t. I much prefer consistency over a minor annoyance.