Vue `nextTick`: Wait for the DOM to Update Before You Touch It

Jakub Andrzejewski

Jakub Andrzejewski

2026-09-21T05:42:53Z

4 min read

One of the first things you learn with Vue is that changing reactive state automatically updates the DOM.

But there is an important detail that can sometimes cause unexpected behavior:

๐Ÿ‘‰ The DOM doesn't update synchronously after every state change.

Vue batches DOM updates and applies them asynchronously. This is an important optimization because multiple state changes can be processed together instead of triggering a separate DOM update for every mutation.

Most of the time, you don't need to think about this.

But sometimes you need to change some state and then immediately work with the resulting DOM.

That's where nextTick() comes in.

In this article, we'll explore:

  • What nextTick() is
  • Why Vue doesn't update the DOM synchronously
  • How to use nextTick()
  • Real-world examples
  • When nextTick() is useful
  • Common mistakes and best practices

Let's dive in.

๐Ÿค” What Is nextTick()?

nextTick() is a Vue utility that lets you wait until Vue has finished flushing pending DOM updates.

The basic API looks like this:

import { nextTick } from 'vue'

await nextTick()
Enter fullscreen mode Exit fullscreen mode

You typically use it after changing reactive state:

count.value++

await nextTick()

// DOM has now been updated
Enter fullscreen mode Exit fullscreen mode

Vue's documentation describes nextTick() as a utility for waiting for the next DOM update flush.

The important part is understanding why you need to wait in the first place.

๐ŸŸข Why Doesn't Vue Update the DOM Immediately?

Imagine you have:

<script setup lang="ts">
import { ref } from 'vue'

const count = ref(0)

function increment() {
  count.value++
}
</script>

<template>
  <button @click="increment">
    {{ count }}
  </button>
</template>
Enter fullscreen mode Exit fullscreen mode

When you execute:

count.value++
Enter fullscreen mode Exit fullscreen mode

Vue knows that the template needs to be updated.

But the DOM isn't necessarily changed immediately.

Instead, Vue buffers the update and processes it during the next update cycle.

This allows Vue to combine multiple state changes:

count.value++
count.value++
count.value++
Enter fullscreen mode Exit fullscreen mode

into a single DOM update instead of unnecessarily updating the DOM three times.

This batching behavior is part of how Vue keeps rendering efficient.

๐ŸŸข The Problem nextTick() Solves

The difference becomes important when you want to access the DOM immediately after changing reactive state.

Consider:

<script setup lang="ts">
import { ref } from 'vue'

const message = ref('Hello')

function updateMessage() {
  message.value = 'Hello Vue'

  console.log(
    document.querySelector('#message')?.textContent
  )
}
</script>

<template>
  <p id="message">
    {{ message }}
  </p>
</template>
Enter fullscreen mode Exit fullscreen mode

You might expect the console to contain:

Hello Vue
Enter fullscreen mode Exit fullscreen mode

But it can still contain:

Hello
Enter fullscreen mode Exit fullscreen mode

Why?

Because Vue has updated the reactive state, but the DOM update hasn't been flushed yet.

That's exactly the situation nextTick() is designed for.

๐ŸŸข A Practical Example: Focusing an Input

One of the most useful real-world examples is dynamically rendering an element and then interacting with it.

Imagine a form where clicking a button displays an input:

<script setup lang="ts">
import { ref, nextTick } from 'vue'

const showInput = ref(false)
const input = ref<HTMLInputElement | null>(null)

async function showAndFocus() {
  showInput.value = true

  await nextTick()

  input.value?.focus()
}
</script>

<template>
  <button @click="showAndFocus">
    Add item
  </button>

  <input
    v-if="showInput"
    ref="input"
    placeholder="Enter item"
  />
</template>
Enter fullscreen mode Exit fullscreen mode

Without nextTick(), this can fail:

showInput.value = true

input.value?.focus()
Enter fullscreen mode Exit fullscreen mode

At this point, the <input> may not exist in the DOM yet because Vue hasn't processed the v-if update.

With:

showInput.value = true

await nextTick()

input.value?.focus()
Enter fullscreen mode Exit fullscreen mode

you wait until Vue has rendered the input.

This pattern is extremely useful for:

  • search fields
  • dialogs
  • inline editing
  • dynamic forms
  • keyboard interactions

๐ŸŸข nextTick() Is Not a General Delay

One common misunderstanding is thinking:

await nextTick()
Enter fullscreen mode Exit fullscreen mode

is equivalent to:

await new Promise(resolve =>
  setTimeout(resolve, 0)
)
Enter fullscreen mode Exit fullscreen mode

They're not the same thing.

nextTick() is specifically connected to Vue's DOM update cycle.

You're not saying:

"Wait some arbitrary amount of time."

You're saying:

"Wait until Vue has flushed the pending DOM updates."

That's a much more precise operation.

๐ŸŸข Don't Use nextTick() Everywhere

It's important not to start adding nextTick() after every reactive state change.

For example, this usually doesn't make sense:

count.value++

await nextTick()

console.log(count.value)
Enter fullscreen mode Exit fullscreen mode

You don't need to wait for the DOM just to read the reactive state.

The value has already changed:

count.value++
console.log(count.value)
Enter fullscreen mode Exit fullscreen mode

The reason to use nextTick() is when you specifically need to interact with the updated DOM.

Think about the distinction:

Reactive state
    โ†“
Already updated

DOM
    โ†“
Updated asynchronously
Enter fullscreen mode Exit fullscreen mode

If you only care about the reactive state, you don't need nextTick().

If you need the DOM to reflect that state, nextTick() can be the right tool.

๐Ÿ“– Learn more

If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:

Vue School Link

It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects ๐Ÿ˜‰

๐Ÿงช Advance skills

A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.

Check out Certificates.dev by clicking this link or by clicking the image below:

Certificates.dev Link

Invest in yourselfโ€”get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!


โœ… Summary

Vue's nextTick() is a small utility, but it solves an important problem: knowing when the DOM has caught up with your reactive state.

The most important thing to remember is:

๐Ÿ‘‰ Use nextTick() when you need to work with the DOM after changing reactive state.

You usually don't need it for normal Vue development. Vue handles reactive updates for you.

But whenever your code needs to say:

"Change this state, wait for Vue to render it, and then do something with the DOM."

that's exactly where nextTick() shines.

Take care!
And happy coding as always ๐Ÿ–ฅ๏ธ