JAVASCRIPT
Deep Component Communication with Vue 3 `provide` and `inject`
Understand how to use `provide` and `inject` in Vue 3 for dependency injection, allowing data to be passed down through deeply nested components without prop drilling.
// ParentComponent.vue
<script setup>
import { ref, provide } from 'vue';
import ChildComponent from './ChildComponent.vue';
const userName = ref('Dr. Who');
const userRole = ref('Time Lord');
// Provide reactive data and functions
provide('userName', userName);
provide('userRole', userRole);
provide('updateUserName', (newName) => {
userName.value = newName;
});
</script>
<template>
<div style="border: 1px solid blue; padding: 10px;">
<h2>Parent Component</h2>
<p>Provided Name: {{ userName }}</p>
<ChildComponent />
</div>
</template>
// ChildComponent.vue
<script setup>
import { inject } from 'vue';
import GrandchildComponent from './GrandchildComponent.vue';
// Inject data from parent
const userName = inject('userName');
const userRole = inject('userRole', 'Guest'); // Second argument is a default value
</script>
<template>
<div style="border: 1px solid green; padding: 10px; margin-left: 20px;">
<h3>Child Component</h3>
<p>Injected Name: {{ userName }}</p>
<p>Injected Role (with default): {{ userRole }}</p>
<GrandchildComponent />
</div>
</template>
// GrandchildComponent.vue
<script setup>
import { inject } from 'vue';
// Inject data and function from ParentComponent (skipping ChildComponent)
const userName = inject('userName');
const updateUserName = inject('updateUserName');
const changeName = () => {
updateUserName('The Doctor');
};
</script>
<template>
<div style="border: 1px solid red; padding: 10px; margin-left: 20px;">
<h4>Grandchild Component</h4>
<p>Injected Name: {{ userName }}</p>
<button @click="changeName">Change Parent Name</button>
</div>
</template>
How it works: This example demonstrates `provide` and `inject` for dependency injection in Vue 3. A parent component uses `provide` to make data (reactive `ref`s and functions) available to all its descendants. Child and grandchild components then use `inject` to retrieve this data, bypassing the need to pass props through intermediate components (prop drilling). `inject` can also accept a default value as a second argument, providing a fallback if the key is not provided by an ancestor.