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
Then open the scaffolded project by the CLI in your IDE.
$ cd vue-3-dependency-injection && code .
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>
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>
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");
<span class="k">return</span> <span class="p">{</span>
<span class="nx">user</span><span class="p">,</span>
<span class="p">};</span>
},
});
</script>
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: "🍕",
});
},
});
Demo
Our client is happy with the functionality that we created, cheers!
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)
Great article. Really helpful an elegant approach.
Is there a similar elegant approach for events?
Thank you man! I'm going to write for that one too soon, stay tuned!