Explain what nextTick() does in Vue, how Vue batches and schedules DOM updates asynchronously, why the DOM is not updated immediately after reactive state changes, and when you must wait for nextTick() to safely read layout or measure elements.
What does nextTick() do in Vue, and why are DOM measurements wrong immediately after a state change?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Overview
In Vue, state changes do not update the DOM synchronously. Vue batches multiple reactive updates and applies them in the next render cycle for performance. nextTick() lets you wait until Vue has flushed all pending DOM updates. If you measure the DOM immediately after changing state, you often read the old layout.
1. The core idea: Vue updates are async and batched
When you change reactive state, Vue does not patch the DOM immediately. It queues the component for re-render and processes all changes together in the next microtask tick.
import { ref, nextTick } from 'vue';
const open = ref(false);
function show() {
open.value = true;
// ❌ DOM is NOT updated yet
}
2. The classic bug: measuring too early
This is why DOM measurements right after a state change are often wrong:
function show() {
open.value = true;
const h = panelRef.value.offsetHeight;
console.log(h); // ❌ Often 0 or old value
}
The template has not been re-rendered yet, so the element is still in its previous state.
3. nextTick(): wait until the DOM is updatednextTick() returns a Promise that resolves after Vue has finished flushing the DOM updates for the current batch.
import { nextTick } from 'vue';
async function show() {
open.value = true;
await nextTick();
// ✅ Now the DOM reflects the new state
const h = panelRef.value.offsetHeight;
console.log(h); // correct value
}
4. What nextTick() actually means
It does not mean “wait one frame” or “wait some time”. It means: wait until Vue’s pending render queue is flushed.
Step | What happens |
|---|---|
| Vue marks components as dirty and queues an update |
| DOM is still old |
| Virtual DOM re-renders and patches the real DOM |
| DOM is now up-to-date |
5. Why Vue does this (performance)
If Vue updated the DOM immediately on every state change, multiple changes in one tick would cause multiple layouts, reflows, and repaints. By batching them, Vue can update the DOM once per tick.
6. Common real-world cases where you need nextTick()
Scenario | Why nextTick is needed |
|---|---|
Opening/closing a panel or modal | You need to measure its size after it appears |
v-if / v-for changes | The element does not exist in the DOM yet |
Scrolling to a newly rendered item | The element is not in the DOM until after render |
Integrating with non-Vue libraries | They expect the DOM to already be updated |
7. nextTick vs setTimeout / requestAnimationFramenextTick() waits for Vue’s render flush, not for a timer or the next frame. It is more precise and faster than setTimeout(..., 0) hacks.
// ❌ Hacky and less precise
setTimeout(() => measure(), 0);
// ✅ Correct
await nextTick();
measure();
8. Subtle case: multiple state changes
Even if you change state multiple times synchronously, Vue will still only update the DOM once, and nextTick() waits for that single final result.
count.value++;
count.value++;
count.value++;
await nextTick();
// DOM is updated once with the final value
Mental model: state changes schedule a render, nextTick waits for that render to finish.
Summary
- Vue batches DOM updates and applies them asynchronously.
- Right after a state change, the DOM is still in the old state.
nextTick()waits until Vue has flushed the pending DOM updates.- Use it whenever you need to read layout, measure elements, or interact with DOM that depends on the new state.