How to set up communication between Vue.js components?
Tags: vue, frontend, typescript, beginners
Published: 2022-05-18 12:38:44

---
title: How to set up communication between Vue.js components?
published: true
date: 2022-05-17 12:01:48 UTC
tags: vue,frontend,typescript,beginners
canonical_url: https://cbonnaud.hashnode.dev/how-to-set-up-communication-between-vuejs-components
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/en0zvo20qcgv32f73ny1.jpg
---

Vue.js is a JavaScript framework allowing developers to create complex and dynamic web applications by assembling custom-made components in a virtual Document Object Model. But how can these components communicate and share data with each other?

# Direct relative

First of all, let's consider this basic case: you have 2 kinds of components, a Parent, who has a given amount of money, and a Child, who can buy articles with the Parent's money.

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787054580/ioV1R3zWb.png"><figcaption>Basic example of communication</figcaption>
</figure>



Now imagine that this parent has 2 children. To know whether he can afford an article with the parent's money, a child has to know the amount of money his parent can provide. In other words, the parent has to indicate to each of his children the amount made available for the purchase of items. We can represent this information by passing a _prop_ **moneyAvailable** to each child.

Then, according to this amount, the child can buy items for a given price. Whenever he does, he has to tell his parent the amount spent, so the amount available for every other child is updated. To do so, we can create an _event_, **purchaseItem** , indicating to the parent the money spent. That is the most common case of communication between components that are directly related: when we go down the tree, we use a prop and when we wind it up, we use an event.

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787384549/odP0OUdEr.png"><figcaption>Parent.vue</figcaption>
</figure>



<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787463880/FrQYpWsGh.png"><figcaption>Child.vue</figcaption>
</figure>


## 2 ways bindings with v-model

For a direct relationship between two components like this, we could use something similar to what's called [2-way binding](https://angular.io/guide/two-way-binding) in Angular by using the _v-model_ directive :

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787522195/BfcRBLCbR.png"><figcaption>Parent.vue - v-model</figcaption>
</figure>

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787561302/AlUhpwJPY.png"><figcaption>Child.vue - v-model</figcaption>
</figure>

_Note_: we can also use getter/setter methods in the child component to be more precise on the control of the data being forwarded, by adding processes before the return statement in the getter and before the emits in the setter :

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787598079/QBHVcEQSm.png"><figcaption>Child.vue - v-model with getter and setter</figcaption>
</figure>

# Indirect relative - bubbling effect

What if we add intermediaries between the children and parents? Let's say now we still have a child and a parent, but we add a sibling who has to approve every purchase. For the moment, the sibling only repeats to the child the money available and tells the parent the amount spent by the child.

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787646455/6-aJ3NcAF.png"><figcaption>Example with an intermediary</figcaption>
</figure>


As we can see in the code, the sibling receives the money available as a _prop_ and forwards it to the child. Then it also handles the **purchase** _event_ of the child and emits a new one to the parent without adding any value.

For a single level, it looks acceptable. However, we can easily imagine how hard it would be if there were several more layers. Each one would have to forward the prop and the events of its own children components.

Let's have a look at the different available solutions.

# Bus Event (Vuejs 2) - External Lib (mitt)

If you're still using Vue 2, there was a common practice that consisted of simulating an event bus by using a second Vue app. You can find more details on how it works in this [article](https://dev.to/bnevilleoneill/using-event-bus-in-vue-js-to-pass-data-between-components-39k4).

However, as mentioned [in this RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md), it is no longer usable in a Vue 3 application. It is suggested to use a tierce library instead, such as [mitt](https://github.com/developit/mitt) to have similar behavior.

# Store

Let's consider the following application.

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787721594/_Cir9yUba.png"><figcaption>Architecture diagramme</figcaption>
</figure>


How can ChildD share some changes with ChildA ? Do we have to emit and trace an event back to the App component? If the Child B and C use data bound to the App, we'll have to add some code inside this component to ensure both children have the latest version of the data. With 2 components listening to a parent, it's achievable. However, if the application grows, bringing new components, and new relationships/dependencies between them, it probably won't be anymore.

When it comes to sharing data and synchronizing components' states, stores are never far away. Even if [Pinia](https://pinia.vuejs.org/) is now the official recommendation for Vue 3, we have to mention that there were 4 versions of [VueX](https://vuex.vuejs.org/) before that ([and Pinia is actually considered as VueX 5](https://github.com/vuejs/rfcs/pull/271)). Broadly speaking, both of them work the same way: they manage stores that have a state which can be represented by an object, actions to perform changes on it, and getters to read it and make sure components are reactive to state changes. Components only have access to the last two, so they don't directly interact with the state.

Therefore, stores are useful if you want to share data across components that are not directly related, or not on the same branch of the DOM. To return to the previous example, where the App component manages a state with 2 components subscribed to it, we can place this state into the store, and create an action to initialize it. This action can perform an HTTP request, set an arbitrary random value to the state or whatever you want, but it will allow any component to initialize/modify/reset this state from anywhere and also make sure that every component that has a getter (representing the dependency between the component and this state) is being updated in real-time. For instance, if our parent has an amount of money placed in the state of a store and several intermediaries who each also have several children under them, every spending component can use a getter on the state _money_ and trigger an action _purchase_ which computes and update the new amount of money available for everybody.

# Composables

Since the release of the Composition API, developers can now create variables and actions totally outside of any Vue component (or even a Vue app actually). Those variables are sharable between components and more importantly, they are reactive, meaning any change on the state will make the component using it re-render.   
On top of that, the declaration and the use inside a component are really simple :

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787760341/MvDxVmGbK.png"><figcaption>Implementation of UseCounter</figcaption>
</figure>

<figure>
  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652787779157/SuQvuRHsj.png"><figcaption>Use of UseCounter</figcaption>
</figure>

It does sound a lot like a VueX/Pinia store with the reactive states, the actions/mutations exposed and the reactivity provided for the components. It might be tempting to replace a state management library with a custom-made composable. However, it is important to understand that we should not confuse features and states management. Pinia and VueX are supposed, as the name suggests, to manage shared-states, **preferably business-related** , throughout the entire application. That has always been their main responsibility and even if they come with actions (and mutation for VueX) to manage their states, they cannot exist without them.

On the other hand, Composables have been designed to help developers to **share functionnalities** across their application. Some of them might have an internal state but that's not mandatory at all. We can take a look for instance at the [VueUse](https://vueuse.org/) library. It's a large toolbox allowing developers to compose their components with the functionalities they want, without reinventing the wheel. Some of them do not have or expose a state.

Lastly, I'd say that it is preferable to use Pinia (or VueX if you want) if you have to handle state management in your application because you'll find a lot of documentation, best practices and pieces of advice, alongside plugins, debugging tools like [Vue Devtools](https://devtools.vuejs.org/), or even built-in features like modularization to help you.