The open blogging platform. Say no to algorithms and paywalls.

Many Ways to Rerender a Vue Component

Photo by Tadeusz Lakota on Unsplash

Photo by Tadeusz Lakota on Unsplash

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we'll look ar the ways to rerender a Vue.js component, and which way is the right way.

The Bad Way — Reloading the Whole Page

The whole point of having a single page app is to not have to reload the whole page to update data. Therefore, it's bad to have the whole page reload to rerender the component.

For instance, we shouldn't write anything like the following code:

Vue.component("foo", {
  data() {
    return {
      names: ["foo", "bar", "baz"]
    };
  },
  methods: {
    reload() {
      location.reload();
    }
  },
  template: `
  <div>
    <button @click='reload'>Reload</button>
    <p v-for='n in names'>{{n}}</p>
  </div>
  `
});

We have location.reload() which we shouldn't call in a single-page app.

Another Bad Way — v-if Hack

The v-if directive only renders the page only when the condition is true. If it's false, it won't be in the DOM.

The v-if hack works by setting the v-if condition to false, and then setting it back to true on the next DOM update cycle by calling $nextTick.

For instance, we can write something like the following code to toggle the render condition to false and then toggle it back to true in the next update cycle:

Vue.component("foo", {
  data() {
    return {
      names: ["foo", "bar", "baz"],
      render: true
    };
  },
  methods: {
    reload() {
      this.render = false;
      this.$nextTick(() => {
        this.render = true;
      });
    }
  },
  template: `
  <div v-if='render'>
    <button @click='reload'>Reload</button>
    <p v-for='n in names'>{{n}}</p>
  </div>
  `
});

We did that by writing:

this.render = false;
this.$nextTick(() => {
  this.render = true;
});

We set this.render to false and then set this.render back to true in the $nextTick callback. This will remove the div from the DOM and then put it back on again.

This will remove the old div component and create a new div component after the $nextTick callback is called.

$nexTick also returns a promise so we can write:

Vue.component("foo", {
  data() {
    return {
      names: ["foo", "bar", "baz"],
      render: true
    };
  },
  methods: {
    async reload() {
      this.render = false;
      await this.$nextTick();
      this.render = true;
    }
  },
  template: `
  <div v-if='render'>
    <button @click='reload'>Reload</button>
    <p v-for='n in names'>{{n}}</p>
  </div>
  `
});

Better Way — Call $forceUpdate

We can call $forceUpdate to force the update of a Vue.js component. $forceUpdate won't refresh the values of computed properties, so it won't work for refreshing computed properties.

To use it, we can write the following:

Vue.component("foo", {
  data() {
    return {
      names: ["foo", "bar", "baz"],
    };
  },
  methods: {
    reload() {
      this.$forceUpdate();
    }
  },
  template: `
  <div>
    <button @click='reload'>Reload</button>
    <p v-for='n in names'>{{n}}</p>
  </div>
  `
});

We just need to add this.$forceUpdate(); to make the component reload.

Photo by Kumiko SHIMIZU on Unsplash

Photo by Kumiko SHIMIZU on Unsplash

The Best Way — Adding Key Props

The best way to ensure that our items refresh properly is to add a key prop with a unique value to the items we render. It'll only recreate the component if the key value matches what we're updating.

The key has to be tied to a specific item on the list so that Vue will know what to update. If this is the case, it'll only rerender the item that has changed in the list since it knows which object is updated in by the unique ID that we set the key value as.

For instance, we can add a key prop to our v-for items as follows:

Vue.component("foo", {
  data() {
    return {
      names: [
        { id: 1, name: "foo" },
        { id: 2, name: "bar" },
        { id: 3, name: "baz" }
      ]
    };
  },
  template: `
  <div>
    <p v-for='n in names' :key='n.id'>{{n.name}}</p>
  </div>
  `
});

We just bind to the key prop with the value we want to and it'll update as needed.

Conclusion

The best way to ensure that v-for items rerender properly is to use the key prop. We just need to pass in a unique ID. $forceUpdate can also be used to reload the page if needed.

Never should we use hacks or reload the whole page.

That's it for this topic. Thank you for reading.




Continue Learning