Accessing Vue Component Data with $ref.
Tags: vue, webdev, javascript, programming
Published: 2022-06-18 08:13:16

> This article assumes you have basic knowledge of Vue & Vue’s reactive system.

Emergencies are a given, and sometimes we get one of those when building frontend applications, thankfully most of these frontend frameworks provide us with multiple ways to handle emergencies. With Vue, one of the many emergency hatches is the `$ref` attribute.

Generally, it’s common to have a ref attribute on pure HTML elements (like the `<input />` element) in Vue, in the same way, you can have a reference on a custom component as well (`<my-custom-componet />`), and have access to its computed values, methods, data properties, and so on. This, however, should only be used in emergency situations or as a last resort.

---

## Accessing Data — The General Approach

Say we have two child components (Component A & Component B) within a parent component and we would for some reason need to display some data from Component A in B and vice-versa. see rough sketch below:

![General approach](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rr3pdkfkicf51jozf4ns.png)
 
The general and recommended approach would be to emit the data from A, add a listener/handler in the parent component, then pass the value into Component B via props. This would look something like this:

![Handler](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/teooiuzlzyv7l0ve03kb.png)
 
In some cases, we might need to hack our way around and eliminate some steps from this flow to make the data passing trip slightly shorter. Say `ComponentA` wouldn’t need to emit its data value to the parent component, then we can remove the emit and listen steps and directly access the values in `ComponentA` from the Parent Component.

![Sharing data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvzrtl6zo6q3pyfd63jk.png)

---

## Using $ref

Say we have two identical components — `Component A` & `Component B`.

Component A has two methods; `setThought` that sets the value of a `thought` data property to any value passed from the editable div, and another method — `readMind` that does nothing for now.
 
{% embed https://gist.github.com/MartinsOnuoha/2965d98723ea4a815d6100ea4f7a19b2.js %}

`Component B` is similar, with just a slight difference in content:

{% embed https://gist.github.com/MartinsOnuoha/d82f0b5085de7499086bf2e7071e43ea.js %}

You may or may not have already figured out what we want to do here. We need Component A to be able to read Component B’s thoughts, without Component B emitting its thought.

For this, both components need to have something in common - their parent. To share data between two components using $ref , they need to be children of the same parent component. So in a parent component, we’ll import Component A and B into a parent component and assign ref attributes to both of them.

{% embed https://gist.github.com/MartinsOnuoha/9923e7a4c860d3da4b54ed2108e61be8.js %}

With this structure, we can easily access each component by reference from its parent like so:

```js
this.$parent.$refs.componentA

OR

this.$parent.$refs.componentB
```

Now we can update the `readMind` method for `Component A` so that on button-click Component A would know exactly what `Component B` is thinking:

{% embed https://gist.github.com/MartinsOnuoha/adf4bd800b17831ef6c3e92728ab70c6.js %}

Notice we can access the `thought` data property in ComponentB by setting a ref attribute on it and accessing it from its parent.


We can make a similar update to the `readMind` method in Component B to do the same thing - find out what Component A is thinking.

{% embed https://gist.github.com/MartinsOnuoha/da78d7f1de2128be46287ede7da55713.js %}

What does this look like?

![Preview](https://devjavu.space/uploads/1_3_ib5zSjcsOjdAGfpDrY9w.gif)
 

---


## Can we set component values too?

Sure, just like the [2010 movie — Inception](https://en.wikipedia.org/wiki/Inception), let’s force Component B’s thoughts to be exactly what Component A thinks about. We can set the value of the data properties in the same way:

{% embed https://gist.github.com/MartinsOnuoha/4db9d4e6cea5ee20c3c0135a9b63c51a.js %}

Alternatively, you can call the `setThought` method of Component B from Component A:

{% embed https://gist.github.com/MartinsOnuoha/c4a65b563b37fea938ed4285aaeaa6cf.js %}

What would this look like?

![image](https://devjavu.space/uploads/1_naoqqfxjlmZNQfXHRylzKQ.gif)

---

## Oh, refs are reactive?

No, they’re not. What you see is only a result of calling the `setThought` method every time there’s an input in Component A and in turn, setting the value of `this.$parent.$refs.componentB.thought` to the same value as the `thought` data property in `ComponentA`.

---

Refs are one of Vue’s quirky parts and can get troublesome if you do not properly understand their usage. The safest way to use them would be outside your lifecycle hooks and only within methods. Also, avoid direct usage within components' template or computed properties.

If you’d like to fiddle around with the source code, you’ll find it here:
[Repository](https://github.com/MartinsOnuoha/vue-ref-example)

Also, [Here’s a detailed guide](https://jefrydco.id/en/blog/safe-access-vue-refs-undefined/) on how and where to safely access refs, and of course, [the official documentation](https://v3.vuejs.org/guide/component-template-refs.html).

Cheers ☕️