JAVASCRIPT
Implementing Deep Component Communication with Vue 3 Provide/Inject
Use Vue 3's `provide` and `inject` to pass data and functions down a deep component tree without prop drilling, enhancing modularity and reusability.
// main.js (optional, for global provides)
// import { createApp } from 'vue';
// import App from './App.vue';
// const app = createApp(App);
// app.provide('app-name', 'My Vue App');
// app.mount('#app');
<!-- App.vue (Parent Component) -->
<template>
<div>
<h1>Provide/Inject Example</h1>
<p>This is the App component.</p>
<ChildComponent />
</div>
</template>
<script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
// Data to be provided
const user = ref({ name: 'Alice', role: 'admin' });
const greet = (name) => `Hello, ${name}!`;
// Provide a reactive value and a function
provide('user-data', user);
provide('greeting-function', greet);
// Simulate updating user data after some time
setTimeout(() => {
user.value.name = 'Bob';
user.value.role = 'user';
}, 3000);
</script>
<!-- ChildComponent.vue -->
<template>
<div style="border: 1px dashed #ccc; padding: 15px; margin: 10px;">
<h3>Child Component</h3>
<GrandchildComponent />
</div>
</template>
<script setup>
import GrandchildComponent from './GrandchildComponent.vue';
</script>
<!-- GrandchildComponent.vue -->
<template>
<div style="border: 1px solid #eee; padding: 10px; margin: 10px;">
<h4>Grandchild Component</h4>
<p>Injected User: {{ injectedUser.name }} ({{ injectedUser.role }})</p>
<p>Greeting: {{ injectedGreet(injectedUser.name) }}</p>
</div>
</template>
<script setup>
import { inject, watch } from 'vue';
// Inject the provided values
const injectedUser = inject('user-data', { name: 'Guest', role: 'viewer' }); // with default value
const injectedGreet = inject('greeting-function', (name) => `Hi there, ${name}.`); // with default function
// Watch for changes in the injected reactive data
watch(injectedUser, (newValue) => {
console.log('Injected user data updated:', newValue);
}, { deep: true });
</script>
How it works: Vue 3's `provide` and `inject` offer a powerful way to communicate data between components that are not directly connected by props or events, often referred to as "dependency injection." A parent component (or the application itself) uses `provide` to make data or functions available, and any descendant component, no matter how deep, can use `inject` to consume that provided data. This avoids "prop drilling" (passing props through many intermediate components) and simplifies state management for widely used values or functionalities. The injected values maintain reactivity if the provided values are reactive.