Vue 3 - ref vs reactive - Which Should You Use?| Sabbirz | Blog

A Practical Guide to ref and reactive in Vue 3

ref vs reactive in Vue

Vue 3 - ref vs reactive - Which Should You Use?

state management Vue.js frontend development Vue tutorial JavaScript vue ref Composition API reactive Vue best practices web development Vue 3 tips ref vs reactive vue3 Vue reactivity ref vs reactive guide reactive state

Navigating the world of Vue 3 often brings developers to a critical crossroads: when should you use ref(), and when is reactive() the right choice? šŸ¤” Both are powerful tools in the Composition API for creating reactive state, but they have key differences that can significantly impact your code's clarity and maintainability.

Let's dive deep, demystify these two functions, and establish clear guidelines to help you write cleaner, more efficient Vue 3 applications.

A developer looking at a screen with the Vue.js logo and code snippets representing ref and reactive.

What is Reactivity in Vue? šŸ’”

Before we compare ref and reactive, let's quickly recap what reactivity means in Vue. At its core, reactivity is the mechanism that allows Vue to automatically track changes to your data and update the DOM whenever that data changes.

In the Composition API, we explicitly declare reactive state using functions like ref() and reactive().

All About ref() šŸ“¦

Think of ref() as a "reference" that can hold any value type — primitives like strings and numbers, or complex types like objects and arrays. It wraps the inner value in a special object with a .value property.

import { ref } from "vue";

// For primitive types
const count = ref(0);
const frameworkName = ref("Vue");
const isActive = ref(true);

// For object types
const user = ref({
  id: 1,
  name: "Alex",
});

How to Access a ref

To access or modify the value of a ref, you must use the .value property inside your <script setup> block.

// Accessing the value
console.log(count.value); // Output: 0

// Modifying the value
count.value++;
console.log(count.value); // Output: 1

// Reassigning the entire object
user.value = { id: 2, name: "Beth" };

✨ Magic Unwrapping: One of the best features of ref is that when used in a template (<template>), Vue automatically "unwraps" it for you. This means you don't need to use .value in your HTML

<template>
  <p>Count is: {{ count }}</p>
</template>

When to Use ref()

  • āœ… For primitive values: string, number, boolean, null, undefined. This is the primary use case for ref.
  • āœ… When you need to reassign the entire variable: ref allows you to completely replace the value it holds (e.g., myRef.value = newValue), which is something you can't do with reactive.

For more details, check out the official Vue ref documentation.

All About reactive() šŸŽ

The reactive() function is used exclusively for object types, such as objects, arrays, Map, and Set. It returns a reactive proxy of the object itself. You don't get a wrapper object with a .value property.

import { reactive } from "vue";

const state = reactive({
  counter: 0,
  user: {
    name: "Chris",
    loggedIn: false,
  },
  items: ["Item 1", "Item 2"],
});

How to Access reactive Properties

You access and modify properties directly on the reactive object, just like a regular JavaScript object.

// Accessing properties
console.log(state.user.name); // Output: 'Chris'

// Modifying properties
state.counter++;
state.user.loggedIn = true;
state.items.push("Item 3");

The "Deep" Reactivity of reactive()

A key feature of reactive is that it provides deep reactivity. This means any nested objects or arrays within the reactive object are also automatically wrapped in reactive proxies. Changes to these nested properties will be tracked.

The Big reactive Pitfall āŒ

There's one major rule with reactive: you cannot reassign the entire object. Doing so will break the reactive connection, and your component will stop tracking changes.

let state = reactive({ count: 0 });

// THIS WILL BREAK REACTIVITY!
// The 'state' variable is now just a plain, non-reactive object.
state = { count: 1 };

Similarly, you lose reactivity if you destructure properties from a reactive object. To work around this, you can use helpers like toRefs.

For more details, see the official Vue reactive documentation.

ref vs. reactive: The Key Differences Summarized

Feature ref() reactive()
Data Types Any value (primitives, objects, arrays) Objects, arrays, Maps, Sets only
Access in Script Via the .value property Directly on the object
Access in Template Automatically unwrapped (no .value) Directly on the object
Reassignment āœ… Safe to reassign the entire ref (myRef.value = ...) āŒ Cannot reassign the entire object
Under the Hood Wraps value in an object. Uses reactive internally for objects. Returns a reactive proxy of the object.

So, Which One Should You Use? šŸ¤”

Here's a simple and effective heuristic followed by many in the Vue community:

  1. Start with ref() for all reactive variables. It works for everything and is consistent. Using .value everywhere in your script makes it clear you're dealing with a reactive variable.
  2. Use reactive() when you have a complex object with multiple properties that you want to group together. Think of it as a single "state" object for your component. This can make your code cleaner by grouping related data.

Many teams default to using ref() for consistency and only use reactive() for large, grouped state objects. There's no single "right" answer, but this approach avoids the common pitfalls of reactive.

Ultimately, the best choice depends on your specific needs and team conventions. The most important thing is to be consistent

Happy coding šŸ’»