Provide and Inject
Sharing data across deeply nested components without threading props through every level in between.
អាន 2 នាទី
Props work well between a parent and its direct child. They get awkward once data needs to reach a component several levels deep — every intermediate component has to accept and re-pass a prop it never actually uses itself, purely so a distant descendant can receive it. This is often called "prop drilling," and provide/inject exists specifically to avoid it.
The problem it solves
<!-- Without provide/inject: theme threaded through every level -->
<!-- App.vue -->
<template>
<Layout :theme="theme" />
</template>
<!-- Layout.vue -->
<script setup>
defineProps(["theme"]);
</script>
<template>
<Sidebar :theme="theme" />
</template>
<!-- Sidebar.vue: still doesn't use theme itself, just passes it further -->
<script setup>
defineProps(["theme"]);
</script>
<template>
<ThemedButton :theme="theme" />
</template>Layout and Sidebar don't care about theme at all — they're just plumbing. Adding a fourth level, or a fifth, means touching every file in between, even though the actual data only matters at the top (where it's defined) and the bottom (where it's used).
provide, at an ancestor
<!-- App.vue -->
<script setup>
import { provide, ref } from "vue";
const theme = ref("dark");
provide("theme", theme);
</script>
<template>
<Layout />
</template>inject, at any descendant
<!-- ThemedButton.vue, nested arbitrarily deep inside App -->
<script setup>
import { inject } from "vue";
const theme = inject("theme");
</script>
<template>
<button :class="theme">Click me</button>
</template>Layout and Sidebar no longer need to know theme exists. ThemedButton asks for it directly by the same string key ("theme") that App.vue provided it under, regardless of how many components sit in between.
Keeping it reactive
Because theme here is a ref, changes made in App.vue (theme.value = "light") are reflected automatically everywhere it's injected — provide/inject doesn't take a snapshot, it shares the same reactive reference.
When to reach for it, and when not to
provide/inject is a good fit for genuinely cross-cutting concerns that many unrelated components at different depths need: a theme, the current authenticated user, localization strings. It's a poor fit as a general replacement for props between components that are already directly related — an implicit, string-keyed connection between two components is harder to trace than an explicit prop declared with defineProps, so use props whenever the parent-child relationship is direct and shallow.
For state that needs to be shared and mutated from many places across an entire application — not just read by deeply nested consumers — a dedicated state management library is usually a better fit than provide/inject. That's exactly what the Pinia lessons later in this course cover.