What the Tick is Vue.nextTick?
Adrià Fontcuberta | January 22nd, 2019 | 3 min read
You start reading Vue’s documentation, and everything seems under control. Props, components, events. Okay. So far so good. This is easier than expected. I’m a pro, now.
But then, as if it were a wild Pokémon, something unexpected appears.
nextTick().
Damn. Just when I started to understand Vue…
Anyway, you don’t panic. You know the drill: calm down and RTFM (internet slang here). I mean, Vue documentation is famous for being one of the best out there, right?
By the way, this is also valid for Vue 3!
Vue.nextTick( [callback, context] )
Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.
Say what?
The what is executed after the next what has what?
I feel your pain.
But fear no more! Vue’s nextTick() may look intimidating at first, but two things you must know:
Its usage is…uncommon. Like one of those silver Magic cards. I have written several Vue apps and ran into nextTick() once or twice.
It’s easier to understand once you’ve seen some use cases. After you get the idea, the fear will go away, and you’ll have a handy tool under your belt.
Let’s go for it, then.
Understanding $nextTick
We are programmers, aren’t we? We’ll use our beloved divide and conquer approach to try to translate the description of nextTickbit by bit. It starts with:
Defer the callback
Ok, now we know it accepts a callback. So it looks like this:
Vue.nextTick(function () {
// do something cool
})
Great. This callback is deferred (this is how millenials say delayed) until…
the next DOM update cycle.
Okay. We know that Vue performs DOM updates asynchronously. It features a way of keeping these updates “stored” until it needs to apply them. It creates a queue of updates and flushes it when needed. Then, the DOM is “patched” and updated to its latest version.
wat?
Let me try again: Imagine your component does something really essential and smart like this.potatoAmount = 3
. Vue won’t re-render the component (and thus the DOM) automatically. It’ll queue up the required modification. Then, in the next “tick” (as in a clock), the queue is flushed, and the update is applied. Tada!
Okay! So we know that we can use nextTick() to pass a callback function that is executed right after the data is set and the DOM has updated.
I can hear your brain screaming.
OMG Adri y u need dis.
As I said earlier… not that often. The “data flow” approach that drives Vue, React, and the other one from Google, which I won't mention, makes it unnecessary most of the time. Yet, sometimes we need to wait for some elements to appear/disappear/be modified in the DOM. This is when nextTick comes in handy.
Use it immediately after you’ve changed some data to wait for the DOM update.
Exactly! This is the last piece of definition that Vue docs provided to us. Inside our callback, the DOM has been updated so we can interact with the “most updated” version of it.
Prove it
Okay, okay. Check this Codepen. Open the console, and you’ll see that the value of our data is updated only inside the callback of nextTick:
See the Pen nextTick playground by Adrià (@afontcu) on CodePen.
A use case
Let’s try to define some useful use case for it.
Imagine that you need to perform some action when a component is mounted. BUT! not only the component. You also need to wait until all its children are mounted and available in the DOM. Damn! Our mounted hook doesn’t guarantee that the whole component tree renders.
If only we had a tool to wait for the next DOM update cycle…
hehehe:
mounted() {
this.$nextTick(() => {
// The whole view is rendered, so I can safely access or query
// the DOM. ¯\_(ツ)_/¯
})
}
In a nutshell
So: nextTick is a comfortable way to execute a function after the data has been set and the DOM has updated.
You need to wait for the DOM, maybe because you need to perform some transformation or you need to wait for an external library to load its stuff? Then use nextTick.
Some people also use nextTick in their unit tests as a way to ensure that the DOM has updated. This way, they can test the “updated version” of the component. Actually, Vue Test Utils returns nextTick for DOM-interacting methods such as setValue
, setChecked
and trigger
, among others. This is why they are async!
Vue.nextTick() or vm.$nextTick()?
Hehehe. Don’t worry. Both are (almost) the same. Vue.nextTick refers to the global API method, while vm.$nextTick() is an instance method. The only difference is that vm.$nextTick doesn’t accept a context as the second parameter. It is always bound to this (also known as the instance itself).
A last piece of coolness
Notice that nextTick returns a Promise, so we can go full-cool with async/await and improve the Codepen example:
async mounted () {
this.message = 'updated'
console.log(this.$el.textContent) // 'not updated'
await this.$nextTick()
console.log(this.$el.textContent) // 'updated'
}
For the sake of completeness
The “next tick” concept isn’t Vue-specific. JS (and thus Node) uses nextTick in the Event Loop, so Vue is keeping things quite standard here.
Pheeew, what a ride. Anyway, now you've mastered nextTick, and you’ll be able to use it appropriately: when you need to perform some action after the DOM updates with your recent changes. Not before.
Hope it helped! 👋
Click to load comments...