JAVASCRIPT
Share Data Across Component Tree with Provide/Inject in Vue 3
Understand how to use Vue 3's `provide` and `inject` to pass data down through a component hierarchy without prop drilling, ideal for global services, themes, or non-reactive data.
// ParentComponent.vue
<template>
<div>
<h1>Parent Component</h1>
<p>Theme from Parent: {{ theme }}</p>
<button @click="toggleTheme">Toggle Theme</button>
<MiddleComponent />
</div>
</template>
<script setup>
import { ref, provide, computed } from 'vue';
import MiddleComponent from './MiddleComponent.vue';
const theme = ref('light');
const appName = 'My Vue App';
const toggleTheme = () => {
theme.value = theme.value === 'light' ? 'dark' : 'light';
};
// Provide a static value
provide('appName', appName);
// Provide a reactive value (ref)
provide('appTheme', theme);
// Provide a computed property for derived state
const headerColor = computed(() => (theme.value === 'dark' ? 'white' : 'black'));
provide('headerColor', headerColor);
// Provide a method
provide('toggleAppTheme', toggleTheme);
</script>
// MiddleComponent.vue (optional, just to show depth)
<template>
<div :style="{ border: '1px dashed grey', padding: '10px', margin: '10px' }">
<h2>Middle Component</h2>
<p>I don't need the provided data, but I pass it down.</p>
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
// ChildComponent.vue
<template>
<div :style="{ backgroundColor: injectedTheme === 'dark' ? '#333' : '#eee', color: injectedHeaderColor, padding: '15px' }">
<h3>Child Component</h3>
<p>Injected App Name: {{ injectedAppName }}</p>
<p>Injected Theme: {{ injectedTheme }}</p>
<p>Injected Header Color: {{ injectedHeaderColor }}</p>
<button @click="toggleInjectedTheme">Toggle Theme from Child</button>
</div>
</template>
<script setup>
import { inject } from 'vue';
// Inject provided values
const injectedAppName = inject('appName');
const injectedTheme = inject('appTheme');
const injectedHeaderColor = inject('headerColor');
const toggleInjectedTheme = inject('toggleAppTheme');
// You can also provide a default value if the key is not found
const fallbackValue = inject('nonExistentKey', 'Default Fallback Value');
console.log('Fallback Value:', fallbackValue);
</script>
How it works: This snippet demonstrates Vue 3's `provide` and `inject` functions for dependency injection, allowing data to be shared across a component hierarchy without 'prop drilling'. In a parent component, `provide(key, value)` makes a value available to all its descendants. The `key` can be a string or a Symbol, and the `value` can be static, a reactive reference (like a `ref` or `reactive` object), a computed property, or even a function. Any descendant component, regardless of its nesting level, can then use `inject(key)` to retrieve the provided value. This pattern is ideal for passing global configuration, theme settings, or service instances to deeply nested components, simplifying data flow and component interfaces compared to passing props through many intermediate components.