Q&A
How to use the Vue.nextTick() method in Vue
Overview
Vue doesn't update the DOM synchronously when you change reactive data. For efficiency, it batches changes and flushes them in a single "tick." So right after mutating state, the DOM still shows the old content. nextTick schedules work for after that flush, when the DOM is current - essential for reading element sizes, focusing newly-rendered inputs, or integrating with non-Vue code.
graph LR
A[Change reactive data] --> B[Vue queues DOM update]
B --> C[DOM NOT updated yet this tick]
C --> D["nextTick(callback)"]
D --> E[Vue flushes DOM updates]
E --> F[Callback runs: DOM is now current]
style D fill:#1e1b4b,color:#fff
The Problem It Solves
// Vue 3 Composition API
import { ref } from "vue";
const message = ref("old");
function update() {
message.value = "new";
console.log(document.getElementById("msg").textContent);
// ⚠ still "old" - the DOM hasn't updated yet this tick
}
The DOM update is queued, not immediate, so reading it right away gives stale content.
Using nextTick (Vue 3)
Import and await it (or pass a callback):
import { ref, nextTick } from "vue";
const message = ref("old");
async function update() {
message.value = "new";
await nextTick(); // wait for the DOM to update
console.log(document.getElementById("msg").textContent); // "new" ✓
}
// callback form:
nextTick(() => {
console.log("DOM updated");
});
Vue 2 Equivalents
this.message = "new";
this.$nextTick(() => {
// DOM is updated here
});
// or the global: Vue.nextTick(() => { ... })
The concept is identical; only the access path differs (this.$nextTick / Vue.nextTick in Vue 2, the imported nextTick in Vue 3).
Common Use Cases
Focus a newly-rendered element
showInput.value = true; // v-if reveals an input
await nextTick(); // wait for it to render
inputRef.value.focus(); // now it exists in the DOM
Measure updated layout
items.value.push(newItem);
await nextTick();
const height = listRef.value.scrollHeight; // accurate post-update size
Scroll to new content
messages.value.push(msg);
await nextTick();
container.value.scrollTop = container.value.scrollHeight; // scroll to bottom
Why DOM Updates Are Async
Batching is a performance optimization: if you change ten reactive values in one function, Vue updates the DOM once afterward rather than ten times. The trade-off is that the DOM lags your data within the same synchronous block - and nextTick is the official hook to run code after the batch is applied.
Why This Matters in Interviews
Vue interviews use nextTick to test understanding of Vue's reactivity and async DOM updates. Key points: Vue batches DOM updates asynchronously (so the DOM isn't updated immediately after a data change), and nextTick runs code after that flush - used for focusing/measuring/scrolling to freshly-rendered elements. Knowing both the callback and await forms, and the Vue 2 (this.$nextTick) vs Vue 3 (imported nextTick) access, shows version awareness. The "why" - batching for performance - is the conceptual core (and parallels React's useEffect/state-batching).
Common Pitfalls
- Reading/manipulating the DOM immediately after changing data (it's stale - use
nextTick). - Trying to access an element revealed by
v-if/v-forbeforenextTick(it isn't rendered yet). - Using
this.$nextTickin Vue 3 setup (nothis; importnextTickinstead). - Overusing
nextTickwhere awatch/computed or proper reactive flow would be cleaner.
References
- Vue
nextTick: https://vuejs.org/api/general.html#nexttick - Vue reactivity & DOM update timing: https://vuejs.org/guide/essentials/reactivity-fundamentals.html