Provide and inject let you share data easily between components without passing props step-by-step. It helps when many nested components need the same data.
Provide and inject for deep passing in Vue
import { provide, inject } from 'vue' // In parent or ancestor component setup() provide('keyName', value) // In child or descendant component setup() const value = inject('keyName')
The keyName is a unique string or symbol to identify the data.
If the injected key is not found, inject returns undefined unless you provide a default value.
import { provide } from 'vue' export default { setup() { provide('color', 'blue') } }
import { inject } from 'vue' export default { setup() { const color = inject('color', 'red') return { color } } }
import { provide, reactive } from 'vue' export default { setup() { const state = reactive({ count: 0 }) provide('state', state) } }
import { inject } from 'vue' export default { setup() { const state = inject('state') return { state } } }
The parent provides a reactive message. The grandchild injects it directly without props. The child is in the middle but does not pass props.
<template>
<div>
<h2>Parent Component</h2>
<ChildComponent />
</div>
</template>
<script setup>
import { provide, reactive } from 'vue'
import ChildComponent from './ChildComponent.vue'
const state = reactive({ message: 'Hello from parent!' })
provide('sharedState', state)
</script>
---
<!-- ChildComponent.vue -->
<template>
<div>
<h3>Child Component</h3>
<GrandChildComponent />
</div>
</template>
<script setup>
import GrandChildComponent from './GrandChildComponent.vue'
</script>
---
<!-- GrandChildComponent.vue -->
<template>
<div>
<h4>Grandchild Component</h4>
<p>{{ sharedState.message }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue'
const sharedState = inject('sharedState')
</script>Provide and inject work only inside the component setup function.
Injected values are not reactive by default unless you provide reactive objects.
Use symbols as keys to avoid accidental key conflicts in large apps.
Provide and inject let you share data deeply without passing props through every component.
Use provide in an ancestor and inject in descendants.
Works great for global settings, themes, or shared reactive state.
Practice
provide and inject in Vue?Solution
Step 1: Understand the role of provide and inject
Provide and inject allow passing data from an ancestor component to any descendant without manually passing props through each intermediate component.Step 2: Compare with other options
Vuex is a separate state management tool, lifecycle hooks handle component events, and CSS variables style components; none of these are the main purpose of provide/inject.Final Answer:
To share data deeply between ancestor and descendant components without passing props. -> Option BQuick Check:
Provide/inject = deep data sharing [OK]
- Thinking provide/inject replaces Vuex completely
- Confusing provide/inject with lifecycle hooks
- Assuming provide/inject is for styling
provide in a Vue 3 setup function?Solution
Step 1: Recall provide usage in setup()
In Vue 3 setup, provide is a function imported from 'vue' and called as provide('key', value).Step 2: Check other options
const provide = { key: 'value' } is an object, not a function call; this.provide = { key: 'value' } uses this which is not available in setup; provide: { key: 'value' } is invalid syntax.Final Answer:
provide('key', 'value') -> Option AQuick Check:
Provide is a function call in setup [OK]
- Trying to assign provide as an object
- Using this inside setup()
- Confusing provide option with function call
import { provide, inject } from 'vue';
export default {
setup() {
provide('color', 'blue');
}
}
// In child component
export default {
setup() {
const color = inject('color');
console.log(color);
}
}Solution
Step 1: Understand provide and inject behavior
The ancestor provides the key 'color' with value 'blue'. The child injects 'color', so it receives 'blue'.Step 2: Confirm no default value or errors
Since 'color' is provided, inject returns 'blue', not undefined or null, and no error occurs.Final Answer:
'blue' -> Option AQuick Check:
Inject returns provided value 'blue' [OK]
- Expecting undefined if not passed as prop
- Assuming inject returns null by default
- Thinking inject throws error if key missing
export default {
setup() {
provide = { theme: 'dark' };
}
}
export default {
setup() {
const theme = inject('theme');
return { theme };
}
}Solution
Step 1: Check provide usage
Provide must be called as a function: provide('key', value). Here, provide is assigned an object, which is invalid.Step 2: Verify other options
Inject default value is optional; key spelling matches; setup can return reactive data.Final Answer:
provide is incorrectly assigned as an object instead of called as a function. -> Option CQuick Check:
Provide must be called, not assigned [OK]
- Assigning provide as an object instead of calling it
- Thinking inject requires default value always
- Confusing setup return rules
Solution
Step 1: Understand reactivity with provide/inject
Provide a reactive object created withreactive()and inject it directly. Vue automatically ensures the injected value is deeply reactive in descendants.Step 2: Analyze other options
Provide a plain object and inject it, then wrap it withreactive()in each child. uses a plain object (no reactivity) and re-wrapping creates separate instances. Provide a ref with the reactive object and inject the ref, then use.valuein children. unnecessarily wraps a reactive object in a ref, adding extra complexity with.value. Provide a reactive object but inject a copy using{ ...injected }to avoid mutation. copies the object, breaking the reactivity connection.Final Answer:
Provide a reactive object usingreactive()and inject it directly. -> Option DQuick Check:
reactive() object + direct provide/inject = preserved reactivity [OK]
- Injecting plain objects and expecting reactivity
- Wrapping injected objects again with reactive
- Copying objects and losing reactivity
Ready to prove it?
Pass the test and this pattern moves unknown
