← Back to all snippets
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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs