Long story short: The cycle never ends !!
The most loved javascript framework… you guessed it right… it’s Vue.js 😉, comes with lifecycle hooks. Which allows us to do specific things at the right time !!
Each Vue component(a view file in Vue.js) goes through a series of must-have initialization steps when it’s created. The actions may be like, data observation, template compilation, mounting the instance to the DOM, and updating the DOM when the data changes.
Every component is a Vue instance, we can modify their states according to our need at specific stages.
In this blog, we will go through the working of Vue 3 lifecycle hooks along with a real-time example.
Deep diving into the context, we will compare Bob’s morning routine with the Vue 3 template rendering and understand how each hook treats our component instance thoroughly.
Bob 🚶= Vue Component’s Instance(Instance) 📑
Initially, Bob is sleeping in the morning and similarly, our Vue instance is uninitialized.
Instance: This hook is called immediately when the instance is initialized, after props resolution, before processing other hooks such as data()
or computed
.
Note that the setup()
hook of Composition API is called before executing any hooks, even beforeCreate()
. The code below demonstrates it.
<script>
export default {
setup() {
console.log("I'm setup hook");
},
data() {
console.log("I'm data hook");
return {
stateOfBob: "sleeping",
};
},
computed: {
test: function () {
return "I'm computed hook";
},
},
beforeCreate() {
console.log("I'm beforeCreate hook");
console.log("Bob is currently ", this.stateOfBob);
console.log("computed hook is returning ", this.test);
},
};
</script>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
If you observed, beforeCreate hook is printing,Bob is currently undefined
which means the variable stateOfBob hasn’t any value assigned yet. Similarly, it’s printing computed hook is returning undefined
because the test
is not called yet and hence not returned anything.
It shows that beforeCreate hook is called before calling data() and computed hook that’s why the variables inside both of them are not having/return any values.
Ultimately, the execution order of the hooks is setup(), beforeCreate(), data().
Bob: I’m sleeping right now 😴.
Instance: This hook is called after the instance has finished processing all state-related options, i.e. data() and computed hooks.
<script>
created() {
console.log("I'm created hook");
console.log("Bob is currently ", this.stateOfBob);
this.stateOfBob = "awakened but still sleeping";
console.log("Bob is currently ", this.stateOfBob);
console.log("computed hook is returning ", this.test);
}
</script>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
I'm created hook
Bob is currently sleeping
Bob is currently awakened but still sleeping
computed hook is returning I'm computed hook
We can justify that created() hook is called after calling data() and computed hooks after seeing the log output.
Also, inside we’ve overridden the stateOfBob variable, as we came to know that it has some value assigned already.
Bob: I’m awakened, but feeling lazy to go out of bed. Let me sleep a few more minutes! 😵.
Between created and beforeMount hooks, some checks are performed. Which checks for whether and how to mount the instance to the DOM.
Bob: Now, fully awakened and go for a refreshment 👣. Looks for brush and towel, if not ready, make it ready 👀.
Instance: This hook is called right before the component is to be mounted.
When this hook is called, the component has finished setting up its reactive state, but no DOM nodes have been created yet. It is about to execute its DOM render effect for the first time.
<template>
<div ref="greeting">Hello readers !</div>
</template>
<script>
beforeMount() {
console.log("I'm beforeMount hook");
console.log("The Dom node is ", this.$refs["greeting"]);
},
</scrip>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
I'm created hook
Bob is currently sleeping
Bob is currently awakened but still sleeping
computed hook is returning I'm computed hook
I'm beforeMount hook
The Dom node is undefined
For testing beforeMount hook’s behavior, we’ve added one div with ref greeting
, which we’re accessing inside beforeMount hook, and the result is all you see !!
It’s telling that I didn’t find a DOM with ref greeting
, hence returning undefined
.
Bob: I’m ready with brush and towel, let me take the shower! 🚿.
Instance: This hook is called after the component/instance has been mounted.
It is typically used for performing side effects that need access to the component’s rendered DOM.
<script>
mounted() {
console.log("I'm mounted hook");
console.log("The Dom node is ", this.$refs["greeting"]);
}
</script>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
I'm created hook
Bob is currently sleeping
Bob is currently awakened but still sleeping
computed hook is returning I'm computed hook
I'm beforeMount hook
The Dom node is undefined
I'm mounted hook
The Dom node is <div>Hello readers !</div>
After adding the above code, you can see the difference between the mounted() and beforeMount() hooks.
The mounted() hook recognizes the ref greeting
, as the DOM node is found already created when the instance calls it.
Bob: I have just taken bath, let me ready for the office 💼.
Between mounted() and beforeUpdate() hooks, again checks performed whether any data changed or not.
Bob: Looking for breakfast on the dining table 🍵 🍴.
Instance: This hook is called right before the component is about to update its DOM tree due to a reactive state change.
This hook can be used to access the DOM state before Vue updates the DOM. It is also safe to modify the component state while executing this hook.
For, example if you want to update the image in your view, you can do it inside the updated hook, but before that, you want to modify the width of your image, which is going to be updated inside updated() hook, then this hook will be a boon for you!
Note that beforeUpdate will not be directly called on page loading, it will be only executed if you update something in DOM. The below snippet will guide you through how you can verify beforeUpdate()’s execution.
<template>
<img ref="img" :src="img" alt="image" width="200" />
<span>comment/uncomment me to see beforeUpdate/updated hook's reactivity</span>
</template>
<script>
export default {
data() {
console.log("I'm data hook");
return {
img: "",
};
},
beforeUpdate() {
console.log(
"I'm beforeUpdate hook and i can help to apply extra effects before a DOM is updated"
);
console.log("width of img div ", this.$refs.img.width);
this.$refs.img.width = 300;
console.log("width of img div after overriding ", this.$refs.img.width);
},
}
<script>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
I'm created hook
Bob is currently sleeping
Bob is currently awakened but still sleeping
computed hook is returning I'm computed hook
I'm beforeMount hook
The Dom node is undefined
I'm mounted hook
The Dom node is <div>Hello readers !</div>
I'm beforeUpdate hook and i can help to apply extra effects before a DOM is updated
width of img div 200
width of img div after overriding 300
We’ve added <img> and <span> in our DOM, the image didn’t have any values initially. But as I mentioned comment/uncomment me to see beforeUpdate/updated hooks reactivity
you need to do the same to test it’s behavior.
In the given example, we had <img> width 200
at first, we overrode it with 300
inside beforeUpdate hook, and it changed!
This claims that we need to modify DOM to execute beforeUpdate/updated hooks.
Bob: Yay! The breakfast has arrived at the table and served to me, let me start eating 😋.
Instance: This hook is called after the component has updated its DOM tree due to a reactive state change.
This hook is called after any DOM update of the component, which can be caused by different state changes.
However, this hook doesn't provide any information on what caused the Vue component instance to be updated. The best way to react to data changes is by using watchers.
It’s recommended to not update any DOM inside the updated() hook, as it’s rendered multiple times.
<script>
updated() {
console.log("I'm updated hook");
this.img = "https://picsum.photos/200/300"; //updates the image src
},
</script>
// Output
I'm setup hook
I'm beforeCreate hook
Bob is currently undefined
computed hook is returning undefined
I'm data hook
I'm created hook
Bob is currently sleeping
Bob is currently awakened but still sleeping
computed hook is returning I'm computed hook
I'm beforeMount hook
The Dom node is undefined
I'm mounted hook
The Dom node is <div>Hello readers !</div>
I'm beforeUpdate hook and i can help to apply extra effects before a DOM is updated
width of img div 200
width of img div after overriding 300
I'm updated hook
You can test updated(), same as has tested beforeUpdate() hook and you will see the image rendered.
Bob: I have completed my breakfast 💪.
Instance: This hook is called right before a component instance is to be unmounted.
Mainly, this hook is useful when you want to clean up your component before destroying it. Cleanup includes clearing intervals and deregistering event listeners. It was known as beforeDestroy
in Vue 2.
Bob: It’s 9 AM, I should leave for the office now. But wait I forgot a tie, let me find it — finding a tie 👀👔… and about to leave a home 🚶.
<script>
beforeUnmount() {
console.log("I'm beforeUnmount hook");
this.$refs.img.width = 0;
},
</script>
If you add the given snippet code in yours, you will notice that it’s successfully executing and makes img’s width 0.
Instance: This hook is the last stop of a lifecycle, called after the component has been unmounted/destroyed. Any of the variables, initialized inside a component are not available inside this hook.
<script>
unmounted() {
console.log("I'm unmounted hook");
this.$refs.img.width = 0;
},
</script>
If we try to make img’s width 0 inside unmounted(), it gives an error like can’t set properties of null (setting `width')
. That’s because before executing the unmounted() hook, all references are being killed !!
Bob leaves the home… 🚴
Now, Alex comes and asks if Bob is there, But Bob has already left the Home 🏠 🚴 !!
Find full code at Vue 3 component lifecycle hooks .
That’s it. Hope you have learned something regarding the Vue lifecycle and it’s working.
Feedback and suggestions are more than welcome 🎉.
keep exploring !!
Whether you need...