·
2 min read

Vue Tip: Use Provide & Inject to Avoid Prop Drilling

Vue Tip: Use Provide & Inject to Avoid Prop Drilling Image

Props are the standard way to pass data from the parent to a child component.

This works well in simple scenarios but has some drawbacks if a deeply nested component needs data from a distant ancestor component:

Prop Drilling

Take a look at the <Footer> component: It needs to declare and pass the props to the <DeepChild> component, even if it does not care about them. Imagine a longer component chain between the parent and the deep child component; all would be affected along the way. This is called "prop drilling" and is no fun for us developers.

Usually, we solve this problem by using state management solutions like Pinia.

But sometimes, we want to share data from a parent component to all its children components without using a store. If you are using Vue 2, you must either use a state management solution or pass the props down to the deeply nested component.

Vue 3 introduced a new concept to solve prop drilling with provide and inject :

Provide Inject

The principle is simple:

  • In the parent component, we declare the variables (props, data, computed, ...), which will be accessible to all descendants via the provide key.
  • From any child component, we specify the list of injectable variables via the inject key

Provide

To provide data to a component's descendants, we use the provide() function:

Root.vue
<script setup> import { provide } from 'vue' provide(/* key */ 'message', /* value */ 'hello!') const count = ref(1) provide('counter', count) </script>

The first argument of the provide() function is the injection key, which can be a string or a Symbol. The descendant component uses this key to look up the desired value to inject. The second argument is the value, which can be of any type, including reactive state such as refs. Using reactive values in the provide() function establishes a reactive connection to the descendant component that injects the value.

As you can see in the above example, it is valid to call provide multiple times with different injection keys and values.

Inject

To inject data provided by an ancestor component, we use the inject() function:

DeepChild.vue
<script setup> import { inject } from 'vue' const message = inject('message') const count = inject('counter') </script>

For more details, check the official docs.

If you liked this Vue tip, follow me on X to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.