blog   |   6 Aug, 2023

Vue: Using provide/inject for component communication

When we're dealing with passing information between parent and child components in Vue, we often use props. Props allow data to move from parent components to their children, making updates in the parent trigger re-renders in the dependent children. But there's a snag: this flow only goes downwards, making it a bit tough to handle when dealing with a lot of components. In big apps with a number of child components in a heirarchy, managing props for each one can get messy.

How do we resolve this? Well, first thing that comes to mind is state management. Here's where Vue offers another workaround known as provide/inject. This pattern sidesteps the complexity of passing props through each child component.

Imagine we have a parent component named App and a child component called ChildComponent. Instead of handing data down using props, we can use provide() in the parent to share data with all its children.

<template>
  <div id="app">
    <ChildComponent />
  </div>
</template>

<script setup>
  import { provide } from "vue";
  import ChildComponent from "./components/ChildComponent";

  provide("data", "Data from parent!");
</script>

Then, in ChildComponent, we use inject() to grab this provided data.

<template>
  <div>
    <p>{{ data }}</p>
  </div>
</template>

<script setup>
  import { inject } from "vue";

  const data = inject("data");
</script>

With this setup, we access the data straight from the parent component without passing it manually through every component in between.

This neat trick still works, even if you have a whole family tree of child components nested within each other. You could have components like ChildComponent2, ChildComponent3, and so on, and still access the parent's data effortlessly.

Besides, you can even provide data at the app level, where the Vue app is created.

import { createApp } from "vue";
import App from "./App.vue";
import "./styles.css";

const app = createApp(App);

// app-level provide
app.provide("data", "Data from parent!");

app.mount("#app");

This app-level provide makes data available throughout all components, which comes in handy when crafting plugins that enhance the entire Vue app.

Now, when do we choose between props and provide/inject? Props are great for passing data step by step, but they can get unwieldy in massive component structures. On the other hand, provide/inject is better when you need to access data from distant parent components, but it might complicate debugging in larger apps.

Generally, use provide/inject for broad, app-wide data like themes or user details, while sticking with props for data confined within specific components.

I hope you enjoyed reading this.