Computer scienceFrontendVue.jsVue 3 Composition API

Refs

8 minutes read

When discussing reactivity in Vue 3, you should consider the ref and reactive functions as two primary elements. These features of the Composition API enable you to create a reactive state and update it automatically. In this topic, you'll delve into the ref function, understanding its syntax and use cases. Additionally, you'll learn about potential pitfalls that might occur when building Vue applications.

What is ref?

The ref, aka reference, is a new function in Vue 3 that can accept any value (primitives or non-primitives) and return a reactive and mutable object. This object isn't a plain JS object though, in fact it's a proxy that can react to changes and update its own value. Every time when the ref variable changes, the component re-renders and shows the updated value. This behavior simplifies the creation of a dynamic state, as Vue automatically updates the state.

To create a reactive state, start by importing the ref function from Vue. You can then initialize a new constant and assign it to ref:

<script setup>
import { ref } from 'vue';

const mobOS = ref('Android');
</script>

In this example, mobOS is a reactive variable, and it equals to "Android" as its initial value. Some people prefer iOS to Android, so let's think of a function that can change our state. It can be a simple function like this:

<script setup>
import { ref } from 'vue';

const mobOS = ref('Android');

const switchOS = () => {
  if (mobOS.value === 'Android') {
    mobOS.value = 'iOS'
  } else {
    mobOS.value = 'Android'
  }
}
</script>

As you can see, the reactive variable was accessed via .value. This is crucial to remember because, within the script tags, the ref values can only be modified or read using .value on the reactive object.

Displaying refs

Suppose a scenario where you want to display your ref in the template and allow the user to modify it. For instance, it could be a button that toggles the state. To implement this, use the following code:

<template>
  <p>I'm a big fan of {{mobOS}}</p>
  <button @click="switchOS" type="button">Change my mind</button>
</template>

The template comprises two elements: a paragraph that renders the state and a button that alters the state. You might have noticed that you didn't need to use .value when accessing the ref variable as you did in the script tag. This is because Vue automatically unwraps it in templates.

The result:

ref example

Try clicking the button to see how state changes. Excellent! Now, you understand how to work with reactivity in Vue 3.

Refs with non-primitives

The cool thing about ref function is that it's universal and can be used with both primitives and non-primitives. Until now, you've built a component with a primitive state. Let's explore how to work with objects. Essentially, the process is identical and straightforward. Here's an example:

<script setup>
import { ref } from 'vue';

const hero = ref({ 
  name: 'kit fox', 
  place: 'Arizona' 
});

</script>

<template>
  <p>Hi! I'm a {{ hero.name }}, you can find me in the canyons of {{ hero.place }}!</p>
</template>

The ref contains an object with two properties: name and place. These are displayed in the template. As you can see, there was no need for any .value in the template. However, if you need to access the state within scripts, your syntax would look like this:

// outputs specific properties
console.log(hero.value.name);
console.log(hero.value.place);

toRef and toRefs

While working in the Vue ecosystem, you may also come across two other functions that resemble ref. These are toRef and toRefs. They are also used to create a reactive state but have slightly different use cases. Let's quickly go over them.

  • toRef()

You might use it when you want to monitor a specific property of a large reactive object. Instead of tracking changes in the entire object, you can destructure some properties and only monitor their changes. The new properties that you created using toRef will maintain their connection to the original object, so any mutations to the toRef properties will reflect in the original object and vice versa.

As you might already know, when you destructure props in the child component, they lose reactivity. The toRef function can help preserve the reactivity of a specific property, even if you destructure it. This is another significant advantage of using it.

A visual example how toRef works:

<script setup>
import { reactive, toRef } from 'vue';

const user = reactive({ 
  name: 'Alex', 
  lastName: 'Coleman',
  age: 25,
  city: 'Seattle',
  // a whole bunch of other properties...
});

const ageRef = toRef(user, 'age');

user.age = 27;

console.log(ageRef.value);

</script>

In this example, you have a state object called user that was created with the reactive function. Don't worry if you're unfamiliar with reactive; it's similar to ref, with one small exception — it can only hold objects or arrays. Suppose this object has over 100 properties, but you only need to monitor one. By using toRef, you instruct Vue to track only the age property of the user object. In doing so, you're optimizing your app because Vue is no longer checking for changes in the remaining 99 properties.

The toRef function takes in a reactive object as a first parameter, and the property as the second one. If you try to change the age property of the user object and then console log the ageRef value, you should see it's also 27. This indicates that the connection to the original object is maintained.

  • toRefs()

The toRefs() function is similar to the previous one, but instead of tracking a single ref value, it can monitor an entire object. You'll find it useful when destructuring props. This function transforms each property of an object into a ref.

Here's an example:

<script setup>
import { toRefs } from 'vue';

const props = defineProps({
  name: String,
  age: Number,
});

const { name, age } = toRefs(props);

</script>

In this code snippet, you defined props and safely destructured them using toRefs. Now, whenever the name or age values change, Vue will adjust the corresponding references as well.

Conclusion

Today, you've learned what refs are in the Composition API and how to use them in a reactive context. The ref function acts as a wrapper for a value and tracks any changes that occur to that value. It can be accessed via .value in the script tag, but the template allows you to omit the .value syntax and reference the value directly. There are also two advanced functions, toRef and toRefs, which can be used with prop destructuring.

2 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo