This article translated from michaelnthiessen.com/force-re-re…

Vue’s responsive system is not always a panacea, and this is where re-rendering components is the solution. Or maybe you just want to uninstall the current DOM and insert a new ONE. How do you correctly re-render a component in this case? The best way to force Vue to re-render a component is to add a :key property to the component. When you need the component to be re-rendered, just change the key value.

It’s an easy solution, isn’t it?

Of course, there are other ways to solve this problem:

  • Reload the entire page
  • Use v – the if
  • Use the forceUpdate method built into Vue
  • By changing the key

That’s what this article will introduce you to.

Refreshing the page, or forcing an update, is obviously not the best approach.

Test your understanding of the following concepts:

  • The response of vUE
  • Calculate attribute
  • Properties to be listened on
  • When v-for is used, it is not added:keyThe habit of

Here ARE some examples of forced updates, most of which will be resolved by changing the key, which I’ll mention at the end of this article.

Reload the entire page

It’s the same way you reboot your computer when you want to shut down an app.

I guess it works sometimes, but the solution is bad.

So much for this approach, don’t do it, let’s find a better way.

Use V-if as a measure of equity

The V-if directive in Vue renders the component when the value is true, and the component does not exist in the DOM when the value is false.

Here’s how v-if works:

In the template tag, add the V-if directive

<template>
  <my-component v-if="renderComponent" />
</template>
Copy the code

In the script tag, add nextTick to the forceRerender function

<script> export default { data() { return { renderComponent: true, }; }, methods: { forceRerender() { // Remove my-component from the DOM this.renderComponent = false; this.$nextTick(() => { // Add the component back in this.renderComponent = true; }); }}}; </script>Copy the code

What these sentences mean is:

  • Initially, the variable renderComponent is set to true and the my-Component component is rendered
  • When forceRerender is called, the renderComponent is immediately set to false
  • My-component components will not be rendered because V-if is set to false
  • In the next task queue, the renderComponent is reset to true
  • Now v-if equals true, my-Component is rendered again

There are two important parts to understanding how these sentences work.

First, you have to wait until the next task queue, otherwise you don’t see any changes

In Vue, a task queue is a single DOM update loop. Vue will collect updates generated in the same task queue and render the rendered part in the DOM based on these updates at the end of the update queue. If we do not wait for the next task queue, these updates will be cancelled and nothing will happen on the page.

Second, when rendering again, Vue will create a new component, that is, Vue will destroy the previous one and create a new one. This means that the new My-Component will go through its usual lifecycle, created, Mounted, and so on.

By the way, you can use nextTick in promises if you want to.

forceRerender() {
  // Remove my-component from the DOM
  this.renderComponent = false;

  // If you like promises better you can
  // also use nextTick this way
  this.$nextTick().then(() => {
    // Add the component back in
    this.renderComponent = true;
  });
}
Copy the code

Even so, this is not a good solution. I call it a stopgap because it’s not the best practice for using Vue.

So let’s look at what the best practices are in Vue.

Use the forceUpdate method built into Vue

This approach is one of the two best ways to solve this problem and is officially supported by Vue.

Typically, Vue responds to changes in the dependent array and updates the view. However, when forceUpdate is called, the view can be forced to update even if there are no changes in the dependent array.

Let me talk about some of the misconceptions that most people have when they use forceUpdate. That is, if Vue updates automatically when a variable changes, why should we force updates?

The reason is that sometimes the Vue’s responsive system gets confused, and we think that the Vue will respond to changes to specified properties or variables, but that doesn’t happen. There are also cases where Vue’s responsive system doesn’t detect any changes at all.

So like the previous approaches, this approach is a better choice if you need Vue’s responsive system to re-render your components.

ForceUpdate can be invoked in two different ways, internally within a component, or globally.

// Globally import Vue from 'vue'; Vue.forceUpdate(); // Using the component instance export default { methods: { methodThatForcesUpdate() { // ... this.$forceUpdate(); // Notice we have to use a $ here // ... }}}Copy the code

Important: This method does not update any calculated properties you already have, and calling forceUpdate simply forces the view to update again.

By changing the key

Most cases require you to re-render a component. Let’s assume that a property key is provided so that Vue knows that a particular component is associated with a particular data. If the key does not change, the component will not change. But if the key changes, Vue knows that it needs to discard the old component and create a new one.

That’s the mechanic we want!

Before we get into this approach, we need to briefly understand why we use keys in Vue.

Why do we need keys in Vue?

Once you understand this, it will help you understand how to force rerender in an appropriate way.

Suppose you render a list of components that has one or more of the following characteristics:

  • The component has its own state within it
  • Components have a process for initialization, especially in the Created or Mounted lifecycle
  • Manipulate non-responsive DOM through apis such as jQuery

If you sort the list, or otherwise update it, you may only want to re-render part of the list. Not every item in the list, just re-render the ones that have been changed.

To help Vue track what has changed and what has not, we provide a property key. The index of an array element cannot be used here because it is not bound to a specific object in the list.

Here is an example of a list:

const people = [
  { name: 'Evan', age: 34 },
  { name: 'Sarah', age: 98 },
  { name: 'James', age: 45 },
];
Copy the code

If we use an index, we write it like this:

<ul>
  <li v-for="(person, index) in people" :key="index">
    {{ person.name }} - {{ index }}
  </li>
</ul>

// Outputs
Evan - 0
Sarah - 1
James - 2
Copy the code

If you remove Sarah, you get:

Evan - 0
James - 1
Copy the code

The index associated with James changes, even though James is still James. James will be rendered, even if we don’t want to.

Therefore, we want to use a unique ID, and there is no limit to how the ID can be generated.

const people = [
  { id: 'this-is-an-id', name: 'Evan', age: 34 },
  { id: 'unique-id', name: 'Sarah', age: 98 },
  { id: 'another-unique-id', name: 'James', age: 45 },
];

<ul>
  <li v-for="person in people" :key="person.id">
    {{ person.name }} - {{ person.id }}
  </li>
</ul>
Copy the code

Until then, if we remove Sarah from the list, Vue will remove the components associated with Sarah and James and create new ones for James. Vue now knows that Evan and James-related components can be kept, simply by removing Sarah.

If we add a Person to the list, Vue will still know that it can keep all the components that currently exist and create a new component separately, inserting it in the right place. This is especially useful if we have a more complex list of components that have their own state, or initialization logic, or any DOM related operations.

It may not be as brief as it seems, but it’s worth explaining how Keys works in Vue.

Let’s move on to the best way to force rerendering.

Force a refresh of a component by changing the key

At this point, this is (in my opinion) the best way to force Vue to re-render components.

If you assign keys to components, you can update the key whenever you want to re-render a component.

Here’s a very basic way:

<template>
  <component-to-re-render :key="componentKey" />
</template>
Copy the code
export default { data() { return { componentKey: 0, }; }, methods: { forceRerender() { this.componentKey += 1; }}}Copy the code

Every time this forceRerender is called, the property componentKey changes. Once this change occurs, Vue will know that it must destroy the component and create a new one.

That way, you get a child component that will be initialized again to reset state.

This is a simple and elegant solution to our problem!

Keep in mind that if you find that you need to force Vue to re-render a component, chances are your code will have some problems.

However, if you need to re-render, it is better to change the key property on the component rather than the other way around.