Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

Using provide/inject in Vue.js 3 with the Composition API

4 min read 1125

Provide Inject API Vue 3

Usually, when we want to pass data from a parent to a child component, we use props. Vue.js has made this straightforward and easy to do. But we’ve probably experienced frustration at some point when we need to pass data from a parent-level component to a deeply nested child component.

If we were to use props, we would end up passing the data to each component on each level of the Vue component tree for the data to get to its final destination. This is called prop drilling and could cause our app to look more complex than it is. And if it were an application with a simple state, using Vuex in it would be overkill.

Luckily for us, Vue has the provide/inject API, and with the introduction of the Composition API in Vue 3, it has never been better.

Using the provide and inject pair, parent components can send data to their children components regardless of how deep the component hierarchy is. The parent component has a provide function to supply data, and the child component has an inject function to start using this data.

Children Components 3 Levels Provide Inject Pair

In the image above, we have three levels of children components. The data we want to pass is contained in the parent component, and the desired destination for the data is deeply nested in the third level of the component tree. We could achieve this using props, but at the expense of our code’s simplicity and readability. Let’s see how we can do this without sacrificing either.

First, we need to install the latest version of Vue CLI v4.5 with the command below:

yarn global add @vue/[email protected]
#OR
npm install -g @vue/[email protected]

The run the command below to create a new Vue app:

vue create provide-inject-tutorial

Using the provide API

The provide API is a function we use to define the data we want to be passed down to a child component.

When using the provide function in setup(), we start by explicitly importing the function from vue. This allows us to define each property when provide is called.

We made a custom demo for .
No really. Click here to check it out.

The provide function accepts two parameters:

  1. The property’s name (a string)
  2. The property’s value (a string or an object containing multiple values)
<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>

After we’ve imported the provide function in the code above, we invoke it inside the setup function. Next, we pass the parameters for the first provide function as follows: the property name 'location' and a single value, 'North Pole'.

For the second provide function, we pass an object containing the latitude and longitude values and set its property name as 'geolocation'.

Using the inject API

The inject API is a function we use to receive data from our provider component.

As we did with the provide function, we also have to import the inject function from vue. This lets us call and use the function anywhere in our component.

The inject function takes two parameters:

  1. The name of the property being injected
  2. An optional default value

Let’s have a look at the code below:

<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>

First we import the inject function into our MyMarker component. Then, inside our setup function, we assign the first provide function with a property name 'location' to the userLocation variable. We also provide an optional default fallback value, 'The Universe'.

Next, we assign the second provide function with a property name of 'geolocation' to the userGeoLocation variable. We return both the userLocation and userGeoLocation variables, after which we are free to use their values anywhere in the MyMarker component.

Making the provide/inject pair reactive

Sadly, straight out the box, the provide/inject pair is not reactive. Thankfully, there is a way to go about making this happen by using either the ref or reactive function provided by the Vue API.

We first have to import them from vue, then we invoke the ref or reactive function. We’ll set its parameters to be the value(s) we want to pass to the desired child component and store the function in a variable. We then invoke the provide function and pass the property name and its value.

Now, if anything changes in either property, the MyMarker component will automatically be updated as well!

We can now update our code as follows:

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>

After importing the ref and reactive functions, we invoke the ref function and give it a parameter (the value 'North Pole') and then assign the ref function to the location variable.

For the reactive function, we invoke it and pass it a parameter in the form of an object. Then we assign the reactive function to the geolocation variable. After we’ve done this, we can call the provide function and pass it the property name and the value of the data we want to pass down.

In the first provide function, we set the property name to 'location' and set its value equal to location, which is the value we assigned to the ref function.

While in the second provide function, we set its property name to 'geolocation' and its value equal to geolocation, which is the value we assigned to the reactive function.

When to use the provide/inject function pair

  • If the app has a fairly simple state and using Vuex would be overkill
  • If your application has too many component levels, and the components in between don’t use the data before it’s passed to the desired component
  • If the data is only used by a few components. But if the data will be used by many more components, Vuex would be a better solution

We’ve learned how to use the provide/inject function pair to pass data between deeply nested components in Vue.js 3 with the Composition API. We’ve covered how to make it reactive and also the different use cases for when you should use it. To learn more about the provide/injectfunction pair, visit the official documentation.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

Leave a Reply