DEV Community

Carlo Miguel Dy
Carlo Miguel Dy

Posted on

Dependency Injection with Vue 3

Introduction

In this article we will be learning how to use Vue's provide and inject.

Installation

Open your terminal and create a fresh Vue project,

$ vue create vue-3-dependency-injection
Enter fullscreen mode Exit fullscreen mode

Then open the scaffolded project by the CLI in your IDE.

$ cd vue-3-dependency-injection && code .
Enter fullscreen mode Exit fullscreen mode

Provide

As an example, let's say our client wants to have the user's name in many places in our application. But there are many ways to do that, but the team decided to only go with provide() so it can supply data to components.

Note: The example scenario may not be so ideal but just to demo how provide() and inject() works

<template>
  <AppFirstChild />
  <AppSecondChild />
  <AppThirdChild />
</template>

<script>
import { defineComponent, provide } from "@vue/runtime-core";
import AppFirstChild from "./components/AppFirstChild.vue";
import AppSecondChild from "./components/AppSecondChild.vue";
import AppThirdChild from "./components/AppThirdChild.vue";

export default defineComponent({
  name: "App",

  components: {
    AppFirstChild,
    AppSecondChild,
    AppThirdChild,
  },

  setup() {
    provide("user", "Carlo Miguel Dy");
  },
});
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
Enter fullscreen mode Exit fullscreen mode

But we can just use props instead? We can definitely pass down props from Parent to child component and this child component passes down this prop to its other child components, and when that child component also has its own child components that needs the data from the root component you pass down props as well.

Actually this is a problem and things might not be that consistent across our application. So the solution to that problem is to use dependency injection with provide() and have all the nested child components use inject() to get the provided data.

Inject Dependency

The one way we can use or get the value from provide() is to use inject(). We'll import that also from @vue/runtime-core. Now let us inject the provided data from our Parent component.

For component AppFirstChild

<template>
  <h1>{{ user }}</h1>

  <AppFirstChildChild />
</template>

<script>
import { defineComponent, inject } from "vue";
import AppFirstChildChild from "./AppFirstChildChild.vue";

export default defineComponent({
  components: {
    AppFirstChildChild,
  },

  setup() {
    const user = inject("user");

    return {
      user,
    };
  },
});
</script>
Enter fullscreen mode Exit fullscreen mode

As you see AppFirstChild component also has a child component. We can also use inject() to get the data provided from the root Parent component easily.

for component AppFirstChildChild

<template>
  <h1>AppFirstChildChild: {{ user }}</h1>
</template>

<script>
import { defineComponent, inject } from "vue";

export default defineComponent({
  setup() {
    const user = inject("user");

    return {
      user,
    };
  },
});
</script>
Enter fullscreen mode Exit fullscreen mode

Provide any data

We are not only limited to provide values as string, we can pass down any type of data. It can be an array, a number, or an object.

So let us provide another data with emojis

export default defineComponent({
  name: "App",

  components: {
    AppFirstChild,
    AppSecondChild,
    AppThirdChild,
  },

  setup() {
    provide("user", "Carlo Miguel Dy");
    provide("emojis", {
      fire: "🔥",
      star: "",
      pizza: "🍕",
    });
  },
});
Enter fullscreen mode Exit fullscreen mode

Demo

Our client is happy with the functionality that we created, cheers!

image

Conclusion

When we want to be consistent in passing down values to other child components across our entire application, we should use provide() and inject() instead as it saves us the time and all the frustrations when just using props.

Thanks for taking the time to read, hope you had a wonderful weekend!

Top comments (2)

Collapse
 
alexandor84 profile image
Oleksandr Sukhotskyi

Great article. Really helpful an elegant approach.
Is there a similar elegant approach for events?

Collapse
 
carlomigueldy profile image
Carlo Miguel Dy

Thank you man! I'm going to write for that one too soon, stay tuned!