DEV Community 👩‍💻👨‍💻

Cover image for When to use ref vs reactive in Vue
Andrew Schmelyun
Andrew Schmelyun

Posted on • Originally published at aschmelyun.com

When to use ref vs reactive in Vue

The release of Vue 3 introduced two new ways of adding reactivity to data in your components: ref() and reactive(). There's been a bit of confusion surrounding which one's better, or when either should be used. I'm here to hopefully shed some light on their differences, and show how I use them in my applications.

Ref

The ref() method takes a single value, and returns back a mutable and reactive object. Let's take a look at this example code:

const amount = ref(0)
Enter fullscreen mode Exit fullscreen mode

If we wanted to create a method that incremented the amount up by one, you might be inclined to think we can do something like this:

const increaseAmount = () => {
    amount++
}
Enter fullscreen mode Exit fullscreen mode

But with ref() you need to use an intermediary property called value in order to retrieve or manipulate the data inside of the ref object. So instead, you'd do:

const increaseAmount = () => {
    amount.value++
}
Enter fullscreen mode Exit fullscreen mode

The ref() method takes any JavaScript primitive, so you can pass in booleans, strings, integers, or objects.

<script setup>
const active = ref(true)
const message = ref('Hello, world!')
const amount = ref(23)
const user = ref({
    name: 'Andrew',
    email: 'andrew@test.com'
})

user.value.email = 'andrew@example.com'
</script>

<template>
    <h1>{{ message }}</h1> <!-- Hello, world! -->
</template>
Enter fullscreen mode Exit fullscreen mode

When referencing or changing a value (outside of a template), you always have to use the .value property on the returned object.

Reactive

The reactive() method works similarly to ref, but it only accepts objects.

// not reactive
const user = reactive('Andrew')

// reactive
const user = reactive({ name: 'Andrew' })
Enter fullscreen mode Exit fullscreen mode

Unlike ref, we don't need to use an intermediary property like .value in order to get or change the properties of our reactive object. We can just call the properties of the object directly:

<script setup>
const user = reactive({ name: 'Andrew' })
user.name = 'Ashley'
</script>

<template>
    <p>My name is {{ user.name }}</p> <!-- My name is Ashley -->
</template>
Enter fullscreen mode Exit fullscreen mode

An interesting feature of reactive() is that it can also unwrap ref objects for use within itself.

const items = ref(10)
const cart = reactive({ items })

items.value++
console.log(cart.items) // 11

cart.items++
console.log(items.value) // 12
Enter fullscreen mode Exit fullscreen mode

The reactivity between the two also remains, so that updating the value of one triggers an update on the value of the other.

The bottom line

Both ref() and reactive() add reactivity to your Vue components. They allow you to have data that updates and responds in real-time across your application. The differences boil down to:

  • What data you're passing in, and
  • If you want to deal with an intermediary property to get the value

For me personally, I usually stick with ref() for reactive attributes in my components. If I start having more than just a few of them though, I create a local "state" object and use reactive() instead.

That way instead of this:

const name = ref('Andrew')
const checked = ref(false)
const games = ref(['Factorio', 'CS:GO', 'Cities: Skylines'])
const elem = ref('#active')
Enter fullscreen mode Exit fullscreen mode

I have this:

const state = reactive({
    name: 'Andrew',
    checked: false,
    games: ['Factorio', 'CS:GO', 'Cities: Skylines'],
    elem: '#active'
})
Enter fullscreen mode Exit fullscreen mode

Well, I hope this made the differences (and similarities) between ref and reactive in Vue a little clearer.

If you have any questions about this, or anything else related to web development, feel free to let me know in the comments or reach out to me on Twitter!

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.