What is nextTick in Vue.js and how can it help large code bases?
One of the common questions people ask me when they start learning Vue is: What does Vue.nextTick do? Will I need to use it in my projects?
What do I answer to them? Yes, of course! I use it regularly on bigger code bases, which has helped me solve a few problems more than once.
☝ But, as with every Vue functionality, it is essential to understand what it does precisely to know when you should rely on it (and when you should not). ♀️ I have seen a few strange scenarios where people used it a lot, bringing a lot of complexity to the app while they should have taken a step back and thought more about the architecture of what they wanted to accomplish.
So that’s why I am writing this article.
But first, let’s talk about the common point of every component: its lifecycle.
The Component Lifecycle
You are probably familiar with the different steps a component goes through ⚙️, but a quick reminder should help a few developers among us.
At
beforeCreate()
is when the lifecycle is initialized. It is called before the Vue engine creates the component, and nothing (events, data, properties, etc.) is set up yet.created()
runs before the DOM is rendered. At this stage, data and events are accessible.beforeMount()
is where the template and scoped styles are compiled, although you still can’t manipulate the DOM, and thevm.$el
instance has not been created yet.When we reach
mounted()
, you can use and manipulate your components any way you want. This means your component belongs to the DOM.beforeUpdate()
is handy for implementing logic ⚙️ before a change is made to your component.updated()
allows you to implement any logic as soon as a change is made to the component.Use
beforeUnmount()
(that replacedbeforeDestroy()
) to clean up your component so you don’t leave any variables or events that could cause memory leaks to your app ️.unmounted()
(replacesdestroyed()
) and can be used to clear intervals or scripts after your component is destroyed .
Now let’s see where our nextTick()
hook falls.
First, What Is Vue.js nextTick?
➡️ According to Vue.js official documentation, nextTick()
is a utility for waiting for the next DOM update flush. This function takes
a callback that will be run once the components’ update is complete. (This update happens when you modify a data property or a computed is changed.)
export default {
mounted() {
this.$nextTick(() => {
console.log(
"I will be displayed once the next DOM update cycle is complete."
);
});
},
};
⚠️ An important thing to remember is that Vue asynchronously updates the DOM (so no matter how many state changes are applied to components during an update, all of them will proceed simultaneously! ☝). Only then, each nextTick()
callback
is called.
These callbacks can be handy when you want to execute something while ensuring that the props, the data or the computed of a children component are updated. ⏲ Your code is delayed after the next DOM update cycle is run and after the browser renders that change.
In other words, the callback is deferred to be executed after the next DOM update cycle.
Why Use Vue.js nextTick When We Can Use settimeout?
As mentioned earlier, Vue asynchronously updates the DOM. So when you make a change to the DOM, it doesn’t happen right away. It kind of checks first that there aren’t any other state changes. ONLY THEN do you see your changes rendered on your browser!
All this happens so fast you don’t even see it. So, why does it matter?
It does matter because, let’s say, you need to run a function right after that change was made. This is where you need to use nextTick()
to wait for the DOM update.
This is for sure why at some point you had to use setTimeout()
(am I wrong? ) because you had to give some time to the browser to update the DOM. Otherwise, your function wasn’t executed. ♀️
☢️ But setTimeout()
has its fallback. It will execute the callback just after the next tick (the DOM update), while nextTick()
prioritizes the callback function execution! ⏱ setTimeout()
delays your callback, as
it first has to give the browser control by using it and only then back to you when its calls your callback function.
Let’s take an example here:
<template>
<h1>{{ message }}</h1>
</template>
<script>
export default {
data() {
return {
message: "Joey doesn’t share food!",
};
},
mounted() {
console.log(this.message);
this.message =
"Well, maybe I don't need your money. Wait, wait, I said maybe!";
console.log(this.message);
setTimeout(() => {
this.message = "Hi, I’m Chandler. I make jokes when I’m uncomfortable.";
console.log(this.message);
}, 300);
this.$nextTick(() => {
this.message =
"It's a moo point. It's like a cow's opinion; it doesn't matter. It's moo.";
console.log(this.message);
});
},
};
</script>
As you can see, nextTick()
is executed before setTimeout()
. This is why using nextTick() will be more performant as it will be run faster!
However, ☝ it’s good to know that as a last resort on browsers that don’t support
nextTick()
, Promise and MutationObserver, it falls tosetImmediate()
on IE 6-10 and tosetTimeout()
for Opera Mini.
WHAT? I hear you whispering: Why not use watch()
to listen for changes? The short answer is that watch()
is used to execute something when the component data changes, while nextTick()
is used to perform code after the app is updated.
Ways To Use Vue.js nextTick
There are two ways to use Vue.js nextTick:
The most common way is to pass a callback function as a first argument. We’ve seen this structure in our earlier example above.
With a Callback Function
mounted () {
this.$nextTick(() => {
this.message = 'Call me maybe!';
console.log(this.message);
});
}
Or await the returned promise you would need if you run into an Uncaught (in promise) DOMException
error. ❌
In a Regular Promise:
mounted () {
this.$nextTick().then(() => {
this.message = 'You promised!';
console.log(this.message);
});
}
With Async/Await:
async mounted () {
await this.$nextTick(() => {
this.message = 'I will always wait for you!';
console.log(this.message)
});
}
Conclusion
Indeed, in small code bases, we seldom need nextTick()
. However, it still has significant advantages, especially if you happen to make API calls and need to run some logic after receiving data from the background.
On the other hand, it is vital to think about the logic of your app. If you use $nextTick
way too often, you might complexify the codebase of your app.
Let me know if I was (or wasn’t ) able to solve the nextTick()
mystery for you. You can reach me on Twitter @RifkiNada, or come and check
my work and articles on www.nadarifki.com.
Bye, coders!