---
title: "Choosing Between Ref and Reactive with Vue 3’s Composition API"
description: "An opinionated perspective on whether you should use ref or reactive in Vue 3’s Composition API."
source: "https://www.netlify.com/blog/2021/03/17/choosing-between-ref-and-reactive-with-vue-3s-composition-api/"
last_updated: "2026-07-10T23:39:47.000Z"
---
When working with Vue 3’s Composition API, a common question that often comes up when working with reactive data is: “Should I use ref or reactive?”

## Quick Overview of `ref`

`ref` is the fundamental building block for reactive data in Vue. As a result, it’s the prerequisite for understanding what’s going on and how things work.

At its simplest, when we want to define data that is reactive and will be watched by Vue, we can do it by importing the helper method and wrapping the desired value in it.

```
import { ref } from 'vue'
const firstName = ref('Ben')const currentCount = ref(10)
return {  firstName,  currentCount}
```

While this is a clean way to declare whether or not a variable contains reactive data or not, it comes with a few downsides:

1.  Requires people to learn the basics of JavaScript proxies
2.  Requires you to unpack the value in some cases but not in others
3.  Adds additional bulk to the code

### The need to understand a little bit about JavaScript Proxies

The thing about `ref` is that whenever you want to refer to the value of the reactive data, you need to be aware of the fact that it will utilize JavaScript Proxies to facilitate the reactivity.

In other words, it has some special properties you must be aware of. Specifically, when you want to refer to the value of a `ref`, you must unpack it by calling `.value`.

```
// Will not give the expected resultconst wrongHeroName = computed(() => { return firstName + ' ' + currentCount})
// Need to access values in order to use them properlyconst heroName = computed(() => {  return firstName.value + ' ' + currentCount.value})
```

### You need to unpack the value in some cases, but not others

This may not seem like a massive inconvenience at first, but it can introduce friction as a learning concept since it’s not always clear when it should be used.

For example, while you need to unpack values manually inside of the script block, once it is returned to the template, you no longer need to unwrap it because Vue will do this for you.

```
<script>import { ref } from 'vue'
export default {  setup() {    const heroName = ref('Taco Launcher')
    return {      heroName    }  }}</script>
<template>  <p>Wrong: {% raw %}{{ heroName.value }}{% endraw %}</p>  <p>Correct: {% raw %}{{ heroName }}{% endraw %}</p></template>
```

### It can add more bulk to the code

Also, for each additional `ref` that you need to expose to the template, you need to manually specify it inside the returned object at the end of your setup function.

```
import { ref } from 'vue'
const firstName = ref('Ben')const currentCount = ref(10)const isTransformed = ref(false)const powers = ref([])
return {  firstName,  currentCount,  isTransformed,  powers}
```

## Quick Overview of `reactive`

On the other hand, `reactive` as a helper method is much closer to what many Vue developers are already familiar with: the `data` option.

In Options API, we would define our code as the following:

```
<script>export default {  data: () => ({    firstName: 'Ben',    currentCount: 10,  }),  computed: {    heroName() {      return this.firstName + ' ' + this.currentCount    }  }}</script>
```

With the `reactive` helper method, we can refactor the `data` option into:

```
<script>import { ref } from 'vue'
export default {  setup() {    const state = reactive({      firstName: 'Ben',      currentCount: 10    })
    return {      state    }  },  computed: {    heroName() {      return this.firstName + ' ' + this.currentCount    }  }}</script>
```

```
<template>  <h1>{% raw %}{{ heroName }}{% endraw %}</h1>  <p>First Name: {% raw %}{{ state.firstName }}{% endraw %}</p>  <p>Current Count: {% raw %}{{ state.currentCount }}{% endraw %}</p></template>
```

And then, unlike `ref`, we don’t have to worry about unpacking any values! You refer to the property as you would expect, without the need to call `.value`. So we can refactor the computed property into the following:

```
<script>import { computed, ref } from 'vue'
export default {  setup() {    const state = reactive({      firstName: 'Ben',      currentCount: 10    })
    const heroName = computed(() => {      return state.firstName + ' ' + state.currentCount    })
    return {      state,      heroName    }  }}</script>
```

And then to top it off, we can utilize a helper method called `toRefs` to minimize the amount of boilerplate code we would ordinarily write with `ref`, while also removing the prefix of `state`!

```
<script>import { computed, ref, toRefs } from 'vue'
export default {  setup() {    const state = reactive({      firstName: 'Ben',      currentCount: 10    })
    const heroName = computed(() => {      return state.firstName + ' ' + state.currentCount    })
    return {      ...toRefs(state),      heroName    }  }}</script>
```

```
<template>  <h1>{% raw %}{{ heroName }}{% endraw %}</h1>  <p>First Name: {% raw %}{{ firstName }}{% endraw %}</p>  <p>Current Count: {% raw %}{{ currentCount }}{% endraw %}</p></template>
```

But like any solution, `reactive` is not without its downside. Because `reactive` is built upon the concept of `ref`, there is a little bit of a circular dependency in that you need to understand `ref` to leverage `reactive` without being too confused.

## Verdict: Use `reactive`

At the end of the day, I recommend using `reactive` as the primary way to manage reactive data in Vue 3’s Composition API. By doing so, it allows us to leverage what developers are already familiar with. And to top it off, it also has the benefit of being more intuitive than `ref`, which requires more in-depth JavaScript knowledge to use.

That said, are there still use cases for using `ref`? Absolutely! It’s just that when it comes to choosing one to primarily stick to, `reactive` is the way to go.

For additional resources on Vue 3’s Composition API, be sure to check out these resources:

-   [Free lesson on reactive data with Composition API Jamstack Explorers](https://www.youtube.com/watch?v=Lwo4BqeAmrc&list=PLzlG0L9jlhENnUuwCPP2IbF5jCCUkmj62&index=4&utm_campaign=devex-bh&utm_source=twitter&utm_medium=social&utm_content=exploreres-comp-api-reactive-data)
-   [Free course on Vue 3’s Composition API](https://www.youtube.com/watch?v=ZA-HCp88guU&list=PLzlG0L9jlhENnUuwCPP2IbF5jCCUkmj62&utm_campaign=devex-bh&utm_source=twitter&utm_medium=social&utm_content=explorers-comp-api-mission)

### Share

-   [X (fka Twitter)](https://twitter.com/intent/tweet?text=Choosing Between Ref and Reactive with Vue 3’s Composition API&url=https://www.netlify.com/blog/2021/03/17/choosing-between-ref-and-reactive-with-vue-3s-composition-api//)
-   [LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.netlify.com%2Fblog%2F2021%2F03%2F17%2Fchoosing-between-ref-and-reactive-with-vue-3s-composition-api%2F%2F)
-   [Facebook](https://www.facebook.com/sharer.php?u=https://www.netlify.com/blog/2021/03/17/choosing-between-ref-and-reactive-with-vue-3s-composition-api//)
-   [Bluesky](https://bsky.app/intent/compose?text=Choosing Between Ref and Reactive with Vue 3’s Composition API+https://www.netlify.com/blog/2021/03/17/choosing-between-ref-and-reactive-with-vue-3s-composition-api//)

* * *

### Tags

-   [Vue](/blog/tags/vue/)
-   [composition-api](/blog/tags/composition-api/)

## Keep reading

![](/images/blog-fallback-thumbnail.svg)

Guides & Tutorials January 12, 2021

[

### Building an Event Registration Page with Composition API and Serverless Functions

](/blog/2021/01/12/building-an-event-registration-page-with-composition-api-and-serverless-functions/)

-   ![Profile picture of Ekene Eze](/_astro/c97b196f1227b05d92404625ecc4779ce8a60661-1000x1000_Z1bjliB.webp)
    
    Ekene Eze
    

![](/_astro/cfdc437592ee2bf75a62690af707d52533d08063-1600x900_2njoni.webp)

Opinions & Insights May 14, 2026

[

### How we built Netlify Database for AI-native development

](/blog/how-we-built-netlify-database-for-ai-native-development)

-   ![Profile picture of Eduardo Bouças](/_astro/52958f21e8450baf6d8e60302341a984e220c0cd-512x512_13VDlu.webp)
    
    Eduardo Bouças
    

## Recent posts

News & Announcements June 25, 2026

[

### Netlify Functions, designed for Agent Experience

](/blog/netlify-functions-designed-for-agent-experience)

-   ![Profile picture of Eduardo Bouças](/_astro/52958f21e8450baf6d8e60302341a984e220c0cd-512x512_13VDlu.webp)
    
    Eduardo Bouças
    

News & Announcements June 24, 2026

[

### How we measure Netlify’s Agent Experience

](/blog/how-we-measure-netlify-agent-experience)

-   ![Profile picture of Sean Roberts](/_astro/bbf2243f8171dbddd80ab2103622106cef84d125-512x512_Z1d2LKE.webp)
    
    Sean Roberts
    

Guides & Tutorials May 15, 2026

[

### How to build a real-time AI chatbot in minutes with Netlify Agent Runners (no backend)

](/blog/how-to-build-a-real-time-ai-chatbot-in-minutes-with-netlify-agent-runners-no-backend)

-   ![Profile picture of Nahrin Jalal](/_astro/f0e7c8f227a03fe58340c99ef5439d5a896c0733-272x272_Z23kDpD.webp)
    
    Nahrin Jalal
    

![](/_astro/3f255b372fa958df35802666ee33b4609b2d71bd-1200x1586_1VtE2D.webp)

### How do the best dev and marketing teams work together?

[Access the report](https://www.netlify.com/reports/2024-leadership-trend-report/access/)