JAVASCRIPT
Efficient Global State Sharing with Provide/Inject in Vue 3
Learn how to manage and share reactive global state across deeply nested components in Vue 3 using the `provide` and `inject` API, avoiding prop drilling efficiently.
<!-- App.vue (Parent component providing state) -->
<template>
<div id="app">
<p>Global Counter: {{ counter }}</p>
<button @click="incrementCounter">Increment Globally</button>
<DeepChildComponent />
</div>
</template>
<script setup>
import { ref, provide, readonly } from 'vue';
import DeepChildComponent from './components/DeepChildComponent.vue';
const counter = ref(0);
const incrementCounter = () => {
counter.value++;
};
// Provide the counter and a method to update it
// Using readonly to prevent direct modification in injected components
provide('global-counter', readonly(counter));
provide('increment-global-counter', incrementCounter);
</script>
<!-- DeepChildComponent.vue (Child component injecting state) -->
<template>
<div class="deep-child">
<h3>Deep Child Component</h3>
<p>Injected Counter: {{ injectedCounter }}</p>
<button @click="callIncrement">Increment from Child</button>
</div>
</template>
<script setup>
import { inject } from 'vue';
const injectedCounter = inject('global-counter');
const incrementGlobalCounter = inject('increment-global-counter');
const callIncrement = () => {
if (incrementGlobalCounter) {
incrementGlobalCounter();
}
};
</script>
How it works: This snippet demonstrates how to use Vue 3's `provide` and `inject` to share reactive state and methods across components without prop drilling. The parent component `provide`s a `readonly` ref for the counter and a function to update it. Deeply nested children can then `inject` these values, accessing the global state and triggering updates without direct parent-child communication. This pattern is ideal for specific feature states or themes that need to be globally accessible without a full-fledged state management library.