What is $nextTick in Vue and When You Need It

What is $nextTick in Vue and When You Need It

This post is more than 2 years old.

I've been using Vue heavily for a while now and this week I ran into an issue that I've never seen before. It's something documented and pretty well known (when I tweeted about it I got a reply in about 60 seconds) but I just had not hit it before. Before I get into $nextTick, let me explain what I was doing and what went wrong.

I have a hidden form on a page that needs to have a dynamic action value. Consider this markup:

<div id="app" v-cloak>
  <form :action="myAction" method="post" ref="myForm">
    <button @click.prevent="testAction">Test</button>
  </form>
</div>

And this code:

Vue.config.productionTip = false;
Vue.config.devtools = false;

const app = new Vue({
  el:'#app',
  data: {
    myAction:null
  },
  methods:{
    testAction() {
      this.myAction = 'http://www.raymondcamden.com';
      this.$refs.myForm.submit();
    }
  }
})

Looks simple enough, right? Probably the only interesting thing here is the use of ref and this.$refs to handle accessing the DOM directly with Vue. I call it fancy because it isn't something I usually need to do with Vue. So what happens when you test this? Try it yourself and see:

See the Pen what the tick?!?! by Raymond Camden (@cfjedimaster) on CodePen.

Instead of POSTing to my server, it sends the POST directly to CodePen, and just today I discovered they support echoing back the data which is kind of cool! (Note, in the embedded CodePen above, the POST echo doesn't work. It may not be a feature of the embed.)

Alright, so what the heck went wrong? Well, if you're like me, you may not have read the "Internals" section of the Vue.js documentation, specifically this part: Async Update Queue.

In case you haven’t noticed yet, Vue performs DOM updates asynchronously.

Raise your hand if you hadn't noticed this yet.

Ray raising his hand

Luckily there's a simple fix for this and if you actually read the title of this post, you have an idea of what it is: this.$nextTick. This function lets you provide a callback to execute when Vue is done propagating your changes to the DOM and it's safe to assume it reflects your new data. The fix is pretty simple:

this.$nextTick(() => this.$refs.myForm.submit());

And if fat arrow functions still confuse you a bit (nothing wrong with that!), here's a simpler version:

this.$nextTick(function() {
	this.$refs.myForm.submit();
});

You can see the corrected version in the CodePen below.

See the Pen what the tick?!?! (fixed) by Raymond Camden (@cfjedimaster) on CodePen.

So to answer the question of "when" - I guess I'd say when you need to ensure the DOM 100% reflects your data and in this case it's kind of obvious - I needed my form POST to use the correct URL. Out of all the times I've used Vue this is the first time I needed this precise level of control but I'm sure I'll run into more examples. If you can, please share an example of when you've used it in the comments below!

Header photo by Franck V on Unsplash

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Rlong posted on 3/30/2020 at 5:14 PM

Used this on one of my Vue components and it fixed the Async issue

Comment 2 (In reply to #1) by Raymond Camden posted on 3/30/2020 at 5:52 PM

Thank you for letting me know it helped!

Comment 3 by m gh posted on 5/1/2020 at 1:20 PM

hi. i want to just say thank you. this issue solved my problem.

Comment 4 (In reply to #3) by Raymond Camden posted on 5/1/2020 at 2:15 PM

Thank you for letting me know, I really appreciate it.

Comment 5 by Sergey Tarkhanov posted on 6/28/2020 at 8:56 PM

Photo super! Really like it.

Comment 6 by Daniel Cohen Gindi posted on 10/19/2020 at 7:12 AM

*edit* I was mistaken, the use case here is not what I thought it was.

This is *not* the use case for $nextTick!
In order to know when the $refs are ready, you can set up a watch (`watch: { ['$refs.myForm']() { /* ref changed */ } }`).
Use $nextTick to do something after updating a value, waiting for the dom to update in response to your change.

Comment 7 (In reply to #6) by Raymond Camden posted on 10/19/2020 at 1:25 PM

I'm sorry - but I don't understand your clarification. Your last sentence is exactly what I was doing. I updated a value (this.myAction). I then wanted to wait for the DOM to reflect that value. I do not see how what you are saying applies here.

Comment 8 (In reply to #7) by Daniel Cohen Gindi posted on 10/19/2020 at 3:20 PM

I’ll try to re-clarify:
In your example, you were not waiting for the DOM update as a consequence if the value update.
These are two separate things. Your value is not included in an “v-if” directive that would change the $refs.
And just a nextTick would not be the ultimate solution, as your method may be triggered from a button click where the $refs is already there, or it may not be there and $nextTick wont change that.
If you use the `watch` feature to know when your ref is available, and perform any pending action.

Comment 9 (In reply to #8) by Raymond Camden posted on 10/19/2020 at 3:22 PM

How is not a DOM update? Maybe that's where I'm confused. If I have <form :action="..."> and I change the value for action, is that not updating the DOM?

Comment 10 (In reply to #9) by Daniel Cohen Gindi posted on 10/19/2020 at 4:03 PM

Oh crap. Now I got you. For some reason I was caught on the $refs, like you were waiting for it to become available, while you were actually waiting for the action to update. My mistake. Apologizes :-)

Comment 11 (In reply to #10) by Raymond Camden posted on 10/19/2020 at 4:35 PM

No worries - and I appreciate you reaching out. As it stands, I couldn't share the "original" demo and had to make a contrived version that probably didn't tell the best story.

Comment 12 by TuffTruth posted on 11/18/2020 at 4:59 AM

Thanks. This really changed things for me!