To pass data from parent to child components, we use props in Vue. But as the application gets complex we may end up having deeply nested components. This means, passing props in every component in the nested chain till the end component gets the data.

In Vue, we can use the provide and inject feature, which can help us avoid using the props to pass data when dealing with deeply nested components.

The provide option is used by the parent component to pass the data to the child component and using the inject option, a child component can access this data.

In this article, we will look at how to declare and implement provide and inject options in Vue.js.

We will begin by creating a new application using Vue CLI.

vue create provide-inject-demo

Once, the installation is complete, we can navigate to the folder and run the server to load the application.

❯ cd provide-inject-demo
❯ npm run serve

This will run our server on port 8080 by default http://localhost:8080/

To demonstrate the provide and inject options, we will create two components:

  • FirstComponent
  • SecondComponent

We will import FirstComponent in the App.vue file and pass some data to the FirstComponent. However, for demonstration purposes, the FirstComponent will not make use of this data. Instead, SecondComponent will be using it.

We will first make use of props to implement it and later replace them with provide and inject options.

Let’s begin by editing the App.vue.

// App.vue

<template>
  <FirstComponent :msg="msg" />
</template>

<script>
import FirstComponent from "./components/FirstComponent.vue";

export default {
  name: "App",
  data() {
    return {
      msg: "Hello World!",
    };
  },
  components: {
    FirstComponent,
  },
};
</script>

In this example, we are declaring a msg property and passing it to FirstComponent.

We haven’t created the FirstComponent.vue file, so let’s create one. We will also go ahead and create another file called SecondComponent.vue which we will be using later.

❯ touch src/components/FirstComponent.vue
❯ touch src/components/SecondComponent.vue

Let’s add some code in FirstComponent.vue.

// FirstComponent.vue

<template>
  <SecondComponent :msg="msg" />
</template>

<script>
import SecondComponent from "./SecondComponent.vue";

export default {
  name: "FirstComponent",
  props: ["msg"],
  components: {
    SecondComponent,
  },
};
</script>

In this component, we are simply passing the msg property to the SecondComponent.

Next, we will add code to the SecondComponent.vue file.

// SecondComponent.vue

<template>
  <h2>Second Component - {{ msg }}</h2>
</template>

<script>
export default {
  name: "SecondComponent",
  props: ["msg"],
};
</script>

In this component, we are just displaying the message sent from the App component.

provide-inject-1

As you can see, to be able to use the msg property in the child component SecondComponent, we had to pass the data via FirstComponent. If we have deeply nested components, the msg property will have to be passed via all the intermediate components in the hierarchy until the child component using the property receives it.

Let’s rewrite the above code using the project and inject options.

In the App.vue we will create a provide method that will include the msg property that needs to be passed.

provide() {
  return {
    msg: this.msg,
  };
}

The entire App.vue file:

// App.vue

<template>
  <FirstComponent />
</template>

<script>
import FirstComponent from "./components/FirstComponent.vue";

export default {
  name: "App",
  data() {
    return {
      msg: "Hello World!",
    };
  },
  provide() {
    return {
      msg: this.msg,
    };
  },
  components: {
    FirstComponent,
  },
};
</script>

Notice, we are not passing msg property in <FirstComponent /> tag.

Now that the provide option is available in the parent component App we will modify both the child component files FirstComponent.vue and SecondComponent.vue.

// FirstComponent.vue

<template>
  <SecondComponent />
</template>

<script>
import SecondComponent from "./SecondComponent.vue";

export default {
  name: "FirstComponent",
  components: {
    SecondComponent,
  },
};
</script>

Notice, we are no longer passing msg prop in the FirstComponent.vue file to the SecondComponent.

Next, we will make changes in the SecondComponent.vue file to include the inject option.

inject: ["msg"];

The entire SecondComponent.vue file:

<template>
  <h2>Second Component - {{ msg }}</h2>
</template>

<script>
export default {
  name: "SecondComponent",
  inject: ["msg"],
};
</script>

provide-inject-1

This way we are able to make use of the msg property in the child component SecondComponent without having to pass props.

Note: The provide and inject options are not a substitute for using props and should be used only when it is necessary.