Please stop using reactive() in Vue 3 Composition API 🙏🏻
Tags: vue, webdev
Published: 2023-12-28 19:38:47

## Intro

When Vue 3 introduced the Composition API, I was really excited about this new way of building components in my favorite framework. And then I was even more excited when **script setup** came out. I love how reactivity works in Vue 3, and in my opinion, it's the simplest and most elegant approach out of all major frameworks. But there is this one thing that we see very often: "Should I use ref or reactive?", "When should I use ref or reactive?", etc. These questions come from people with varying levels of experience, and there are some battles over the internet where people are trying to create "rules of thumb" for which scenario you should use **ref()** or **reactive()**. I've seen some statements like "ref for primitives, reactive for objects and arrays," and let's put it mildly, I don't agree 😀. Why overcomplicate something that should be so damn easy? It's easy.

## Just always use ref()

Why? Because **ref()** can do everything that **reactive()** can, but **reactive()** can't do anything that **ref()** can. So the first question is, why would you mix these different reactivity functions?

```vue
<script setup lang="ts">
import { ref, reactive } from 'vue';

const searchPhrase = ref('')

const searchOptions = ref({
    matchCaseSensivity: false,
    includeIgnoredItems: false
})

const showAdvancedSearch = ref(false)
</script>
```

then

```vue
<script setup lang="ts">
import { ref, reactive } from 'vue';

const searchPhrase = ref('')

const searchOptions = reactive({
    matchCaseSensivity: false,
    includeIgnoredItems: false
})

const showAdvancedSearch = ref(false)
</script>
```
?

If you create artificial rules like "ref for primitives, reactive for objects and arrays," you introduce unnecessary mental overhead by having to make that decision every time. However, you might ask, "If I can use ref for everything, why does reactive exist?" That's a good question. When using **ref()**, you have to access the value through the **.value** property.

```vue
<script setup lang="ts">
import {ref} from 'vue';

const searchPhrase = ref('')

function clearSearchPhrase() {
    searchPhrase.value = ''
}
</script>
```

same with objects and arrays:

```vue
<script setup lang="ts">
import {ref} from 'vue';

const newItemName = ref('')
const items = ref([])

function addItem() {
    items.value.push(newItemName.value)
}
</script>
```


And if you would like to use **reactive()**:

```vue
<script setup lang="ts">
import {ref, reactive} from 'vue';

const newItemName = ref('')
const items = reactive([])

function addItem() {
    items.push(newItemName.value)
}
</script>
```
With **Reactive**, you don't have to use **'.value'** to access the value of a reactive variable. Someone might say, "Oh, so it's better than ref! I don't want to add .value every time." I can sort of understand that, but take a look at the example above one more time. Can you see the problem? Sometimes it's **ref()**, sometimes it's **reactive()**. Sometimes it's **'.value'**, sometimes not. In large codebases, it can be confusing.

I think the necessity of using **.value** makes you more aware of when you are using reactive variables or not. It's easy to search the codebase. Trust me, I saw a lot of bugs produced by forgotten '.value' or '.value' being present where it should be because someone used **reactive()**.

**Keeping it short: `ref` is more universal, and you can create the whole project with `ref()` only to make your code consistent. When you decide to use `reactive()`, you will also have to use `ref()`, and your codebase will be mixed with different approaches, which can cause a lot of bugs.**

Another limitation of **Reactive** is the fact that it can't replace the entire object, while **Ref** can.
```js
let state = reactive({ count: 0 })

// the above reference ({ count: 0 }) is no longer being tracked
// (reactivity connection is lost!)
state = reactive({ count: 1 })
```
If you are still not convinced, let's check if maybe the Vue docs are saying something about the preferred way.

[Oh yes!](https://vuejs.org/guide/essentials/reactivity-fundamentals#ref), the official docs statement is:

***"In Composition API, the recommended way to declare reactive state is using the ref() function"***

And one last thing: I understand that there might be super rare edge cases, especially for library authors, where **reactive** might be a better choice. If you think that, in a particular scenario, **reactive** is the better option and you are really confident about it, then go for it! My point is that **ref** should be your default choice, and if somehow you end up with this super rare edge case, you can go with **reactive**`. Let's make it easy and not overthink this, making it easier for other people working on the same project. 🙏🏻

----------
⭐ ***If you like my posts, please follow me on Twitter:***
https://twitter.com/michalkuncio