How to make provide/inject reactive
Tags: vue, javascript, tutorial, webdev
Published: 2019-10-13 19:32:51

---
title: How to make provide/inject reactive
published: true
date: 2019-10-12 14:00:14 UTC
tags: vue,javascript,tutorial,webdev 
canonical_url: https://blog.logrocket.com/how-to-make-provide-inject-reactive/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/i7q03qpqabiimug4wify.png
---
**Written by [Michael Thiessen](https://blog.logrocket.com/author/michaelthiessen/)**✏️

By design, the `provide` and `inject` features of Vue are [not reactive](https://vuejs.org/v2/api/#provide-inject), even though many people (myself included!) wish they were.

That’s not a huge problem for us though since there is a way to get around this:

**If you create a reactive object using the `data()` function or `Vue.observable`, it will still be reactive when passed down using `provide` and `inject`.**

It would look like this if you’re using the data function:

```jsx
export default {
  provide() {
    return {
    reactive: this.reactive
    };
  },

  data() {
    return {
    reactive: {
        value: "Hello there"
    }
    };
  }
};
```

Now when `reactive` is injected into another component, it will behave like any other prop and changes to `reactive` will trigger updates in your Vue application!

## TL;DR

In this article we’ll cover:

- Why the `data()` function is a great solution to this problem
- The simplest method for making objects reactive, **even outside of Vue**
- A library by a Vue core team member that handles it all for you
- Questions to help you determine when it’s a good time to use reactive provide/inject
- Why you should be careful to **avoid two-way data binding**

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## But first, a warning

This should _only_ be used in special circumstances. This technique should not be used as a replacement for props and events. If all you need is a basic way to pass data around, props and events are great, simple, and everyone else who reads your code will understand what’s going on.

So when should you use it?

We’ll cover that a little later on, but first, let’s take a look at three different ways we can make provide and inject reactive.

## Using the data() function

The first technique is to make the object reactive by initializing it in our `data()` function:

```jsx
export default {
  provide() {
    return {
    reactive: this.reactive
    };
  },

  data() {
    return {
    reactive: {
        value: "Hello there"
    }
    };
  }
};
```

Any object that is initialized here will be made reactive by Vue. Once it is reactive, it is reactive no matter where it gets used.

You can even pass the object to some random JavaScript outside of your Vue app, and any changes made to the reactive object will trigger updates inside of your Vue app.

There is a second way we can make our object reactive, something that’s fairly new to Vue.

## Using Vue.observable

[Vue 2.6](https://github.com/vuejs/vue/releases/tag/v2.6.0) introduced the `observable` function that lets us [create our own](https://vuejs.org/v2/api/#Vue-observable) reactive objects:

```jsx
import Vue from 'vue';
const state = Vue.observable({ message: "Hello!" });
```

In fact, this is the same function that Vue uses internally with the `data()` function, but here it is exposed to us so that we can use it wherever we want.

In Vue 3, this function will be renamed to `reactive` with the addition of the [Composition API](https://github.com/vuejs/rfcs/pull/78).

Let’s rewrite the previous example to use `Vue.observable`:

```jsx
import Vue from 'vue';

const reactive = Vue.observable({ value: 'Hello there' });

export default {
  provide() {
    return {
    reactive: reactive,
    };
  },
};
```

This function gives us a lot more flexibility in how we create our reactive objects since we are no longer reliant on the `data` function.

However, in most cases, you’ll be using the previous method because the state that you’re providing will typically already be initialized by the `data()`function. But this is a great tool to add to your toolbox in case you ever find that the `data()` function just doesn’t quite do what you need it to.

The final method we’ll cover is not a native Vue feature, but a mixin created by Vue core team member [Linus Borg](https://twitter.com/linus_borg?lang=en).

## Linus Borg’s mixin

Linus, who is a member of the Vue core team, has created the `vue-reactive-provide` mixin, which you can find on [Github](https://github.com/LinusBorg/vue-reactive-provide).

It’s a super easy way to make provide/inject reactive if you don’t like the other options, and there are two main ways you can use it.

## Component option

If you want it to feel similar to the native `provide`, you just have to install it as a plugin:

```jsx
import Vue from 'vue';
import ReactiveProvide from 'vue-reactive-provide';

Vue.use(ReactiveProvide);
```

You would add this to your `main.js` file if you’re using Vue CLI.

Then in the component where you want to provide the value, you would use `reactiveProvide` instead:

```jsx
export default {
  reactiveProvide: {
    name: 'injectedName',
    include: ['reactive'],
  }

  data() {
    return {
    reactive: 'hello',
    };
  },
};
```

You need to give your reactive object a `name` so we know what value to inject in the child. Then you can include any number of fields that you want using the `include` array.

To inject this reactive object into a component you would inject it like normal, using the `name` value you set earlier:

```jsx
export default {
  inject: ['injectedName']
};
```

## Mixin

Using it as a mixin is nearly the same process, but you don’t need to register it as a plugin first:

```jsx
import { ReactiveProvideMixin } from 'vue-reactive-provide'

export default {
  mixins: [
    ReactiveProvideMixin({
    name: 'injectedName',
    include: ['reactive'],
    })
  ],

  data() {
    return {
    reactive: 'hello',
    };
  },
};
```

We use the `ReactiveProvideMixin` function to dynamically create a mixin. The mixin will provide the included value in a reactive way for us.

To inject the value, we use the exact method as before:

```jsx
export default {
  inject: ['injectedName']
};
```

## When to use reactive provide/inject

In general, you should try to avoid using provide/inject, and instead pass data around using props and events. That will get you where you need to go most of the time, and you avoid adding unnecessary complexity and keep your code understandable.

However, there are a few specific questions you can ask yourself when deciding whether or not you should use this feature:

1. **Do you need to avoid prop drilling?** — It can get tedious to pass a prop down through layer after layer of components, especially when those intermediate components don’t actually use the prop. This can also be solved by [Vuex](https://vuex.vuejs.org/), but you sometimes want a simpler and lighter solution
2. **Are the components tightly coupled?** — If you have a set of components that will always be used together, then it’s okay to rely on provide/inject to pass some of the data around. Otherwise, it’s best to stick with props and events, which is what most other components will be using
3. **Is Vuex overkill?** — Vuex is a great tool, but if you’re dealing with something that has a simple state, then Vuex is overkill and introduces a lot of overhead. If the set of components needs to be reusable, then coupling it with Vuex also introduces unnecessary complexity
4. **Is the data contained within a few components?** — If the data being passed around is only used by a couple components, then this solution can make sense. But if the data being used here is used elsewhere, keeping it higher up in the tree _or_ using Vuex can be better solutions

Your use case doesn’t have to pass _all_ of these rules, but it should fit at least one or two of them.

For example, let’s imagine you were working on an app that had fairly straightforward state. Vuex would be overkill, so you’ve decided not to use it.

Each page loads the user’s information in a `user` object, and that object is used in all sorts of places all over the app. Displaying the user’s name, their email address, and other information like that is not limited to a specific part in the application.

To avoid passing this data as prop through _every single component_ in our app, we `provide` it at the top-level component, so any component that needs it can `inject` the `user` object and gain access to it directly.

Now, this might seem to violate our fourth rule, but it hits #1 and #3 right on the head. So this ends up being a great solution.

Before we wrap up, there’s one other thing that you should be sure to avoid when using this technique.

## Avoid two-way data binding

When you use a reactive injection like this, a common mistake is to treat it as a two-way binding, where the value can be changed by the component providing it, as well as the one injecting it.

But this is a horrible idea? Only the component that is providing the value should ever be allowed to modify it.

This is for two main reasons:

1. Vue uses a one-way binding system where data flows down the tree. Using a different data flow model in one spot of your app will make it inconsistent and will cause a lot of confusion
2. Keeping all of the mutations in a single component makes it much easier to update, refactor, and track down bugs in the future

## Conclusion

As we saw, it _is_ possible to make provide and inject reactive, and it doesn’t take too much effort. There are three different ways to do it, so you’ll be able to find something that fits your project.

This technique is really useful, but as I mentioned, it can also make your code unnecessarily complicated. It’s best to stick with regular props and events if that will work for you.

If props and events aren’t working well, we went through a few different questions you can ask yourself to determine if this technique is right for your use case.

Lastly, we covered what two-way data binding is and why you should avoid it.
* * * 
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/how-to-make-provide-inject-reactive/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [How to make provide/inject reactive](https://blog.logrocket.com/how-to-make-provide-inject-reactive/) appeared first on [LogRocket Blog](https://blog.logrocket.com).