← Back to all snippets
JAVASCRIPT

Avoiding Prop Drilling with Vue 3 `provide` and `inject`

Understand how Vue 3's `provide` and `inject` functions enable efficient data sharing between deeply nested components without cumbersome prop drilling.

// ParentComponent.vue
<template>
  <div>
    <h1>Parent Component</h1>
    <button @click="toggleTheme">Toggle Theme</button>
    <IntermediateComponent />
  </div>
</template>

<script setup>
import { ref, provide, readonly } from 'vue';
import IntermediateComponent from './IntermediateComponent.vue';

const currentTheme = ref('light');

const toggleTheme = () => {
  currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light';
};

// Provide a reactive value (and a way to update it, if needed)
// Using readonly to prevent child components from directly modifying currentTheme
provide('theme-key', readonly(currentTheme));
provide('toggle-theme-key', toggleTheme);
</script>

// IntermediateComponent.vue
<template>
  <div class="intermediate">
    <h2>Intermediate Component</h2>
    <p>I don't need the theme, but I pass through.</p>
    <GrandchildComponent />
  </div>
</template>

<script setup>
import GrandchildComponent from './GrandchildComponent.vue';
</script>

<style scoped>
.intermediate {
  border: 1px dashed #ccc;
  padding: 10px;
  margin: 10px 0;
}
</style>

// GrandchildComponent.vue
<template>
  <div :class="['grandchild', theme]">
    <h3>Grandchild Component</h3>
    <p>Current Theme: {{ theme }}</p>
    <button @click="toggleTheme">Toggle Theme (from Grandchild)</button>
  </div>
</template>

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

// Inject the provided values
const theme = inject('theme-key');
const toggleTheme = inject('toggle-theme-key');
</script>

<style scoped>
.grandchild {
  padding: 15px;
  border-radius: 8px;
  margin-top: 10px;
}
.grandchild.light {
  background-color: #e0f2f7;
  color: #333;
}
.grandchild.dark {
  background-color: #333;
  color: #f0f0f0;
}
</style>
How it works: `provide` and `inject` in Vue 3 offer a dependency injection system, allowing a parent component to provide data that can be injected by *any* descendant component, regardless of how deep it is in the component hierarchy. This eliminates 'prop drilling' – passing props through many intermediate components that don't directly need them. Here, `ParentComponent` provides `currentTheme` and a `toggleTheme` function. `GrandchildComponent` directly injects and uses these values without `IntermediateComponent` needing to know about them.

Need help integrating this into your project?

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

Hire DigitalCodeLabs