How Provide and Inject work in Vue
Tags: vue
Published: 2022-07-31 12:53:00

It's easy in Vue to provide/give props or properties to a child element. [Properties in Vue](https://fjolt.com/article/vue-how-do-props-work) are one of the main ways we can pass data from a parent element or vue template to a child element. For example, in the code below, we give our child element `PopularList` the property `name`, and set it to `Most Popular Posts`. That means that `PopularList` can now access the data `Most Popular Posts`:

```javascript
<PopularList name="Most Popular Posts" />
```

**However**, sometimes child elements can contain other child elements. If we want to pass data from a parent component, to a grandchild component, an easier way of doing this is with **provide**/**inject**. This lets us **provide** data at a parent level, and **inject** it at any level below that.

This means if we have a property which is not used by the child, but is used by the **grandchild**, we don't have to unnecessarily pass it through both, like `Parent → Child → GrandChild` - we can instead simply pass it as `Parent → Grandchild`, as shown in the diagram below:

![Provide and Inject Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i54yt98rxvni89yadzn.png)
 
 

## How to use provide and inject in Vue

If you are using the composition API, you can `provide` any set of data using the `provide` function:
```html
<script setup>
    import { provide } from 'vue'
    provide('myKey', 'message');
</script>
```


`provide` has both a key, and a value - above, the key is `myKey`, and the value is `message`. As with props, this could be an object, or a number, or any other valid type. We can also make this property reactive, so it stays up to date in the grandchild element by using the `ref` function:
```html
<script setup>
    import { provide, ref } from 'vue'
    const message = ref('message');
    provide('myKey', message);
</script>
```

If you are using the Options API instead, you can provide data in a component using the following structure:
```javascript
export default {
    provide: {
        myKey: 'message'
    }
}
```

If you want the Options API version of reactivity in `provide`, you have to use `computed`. As such, the composition API is a little more straightforward to use with `provide/inject`. We also need to use the `provide()` notation if we are giving any per-instance state - i.e. where the data is coming from the `data()` function.
```javascript
export default {
    data() {
        return {
            message: 'message'
        }
    },
    provide() {
        return {
            // This sets `myKey` to the message property from data().
            // Putting it in `computed()` makes it reactive.
            myKey: computed(() => this.message)
        }
    }
}
```

**Now** that we've provided data, it can be accessed in any child component at any level by using the `inject` function.

### Accessing parent data using inject in Vue

Now that we've defiend `provide` in a component, you can access that data using `inject`. In a child component, or a grandchild component, we can access `myKey` to refer to `message`. For example, suppose we have a Vue component which looks like this:
```html
<script setup>
    import { ref, provide } from 'vue'
    import ChildElement from './Child.vue';
    const message = ref('message');
    provide('myKey', message);
</script>
<template>
    <p>Hello World!</p>
    <ChildElement />
</template>
```

... And then a child element (`Child.vue`) that looks like this:
```html
<script setup>
    import GrandChildElement from './GrandChildElement.vue';
</script>
<template>
    <GrandChildElement />
</template>
```

Within `GrandChildElement`, we can access `myKey`, since we provided it in a parent. We could also do this in `Child.vue`, but we could also just use props for that. `provide` gives us the power to get data from multiple levels up. To access this data in `GrandChildElement`, we use `inject`. Our `GrandChildElement.vue` file could look a little like this:
```html
<script setup>
import { inject } from 'vue'
const message = inject('myKey')
</script>
```
`const message` here will return the text `message`, since that's what we set `myKey` to with `provide`. If you're using the Options API, you can do this instead:
```javascript
export default {
    inject: [ 'myKey' ],
    created() {
        // Can access this.myKey here
    }
}
```

Now the value of `myKey` is available to a grandchild component, without the need to pass it to the child first via props.