You may have an infinite update loop in a component render function

node.jsvue.jsVuejs2

node.js Problem Overview


I'm new to VueJS, I've got warning from Vue,

[Vue warn]: You may have an infinite update loop in a component render function. 

When i use V-for variable in V-bind:style, here is an example : in template :

<div v-for="item in model.items" v-bind:class="test(item.result)">
{{item.id}}
</div>

in script :

data() {
    return {
        accept: false,
        not_accept: false,
    };
},
methods: {
    test(result) {
        if (result == 'accept') {
            this.accept = true;
            this.not_accept = false;
        } else if (result == 'Not accept') {
            this.accept = false;
            this.not_accept = true;
        } else {
            console.log(result);
        }

        return {
            success: this.accept,
            danger: this.not_accept,
        };
    },
},

node.js Solutions


Solution 1 - node.js

@Decade is right about the problem. Here is the exact problem:

  1. You are in render method rendering the list of item using some state value

> NOTE: render method is triggered whenever any state changes

  1. Then you are trying to bind the class based on a result of function test this function is flawed as it is again trying to mutate the state, thus causing the render - test - render cycle.

You can solve this problem by making your test function not mutate the state instead, like so:

methods: {
    test(result) {
        let accept;
        if (result == 'accept') {
            accept = true;
        } else if (result == 'Not accept') {
            accept = false;
        } else {
            console.log(result);
        }

        return {
            success: accept,
            danger: !accept,
        };
    },
}

I hope that helped!

Solution 2 - node.js

First, I'm not sure why you have not_accept, can't you just use !this.accept in its place?

I'm not 100% sure why you're getting this warning, but here's what I think.

The watcher for v-bind:class is watching for changes to item.result, this.accept and this.not_accept. Any change in those values will cause it to be re-rendered by calling test again. But within test, you're modifying this.accept and this.not_accept, so Vue needs to re-check again if the result has changed because of that, and in doing so it may change this.accept and this.not_accept again, and so on.

The class binding and the data is flawed. class for each of the items will be set to the same thing, but it looks as though you want a custom style for each item depending on item.result. You really shouldn't be modifying any properties of this inside test.

It's hard to give a thorough answer because I'm not completely sure of how your component works and what it should do.

Solution 3 - node.js

I was accidentally doing something similar and not that easy to spot with an untrained eye: calling .sort() on an array in a filter. sort mutates the array, thus making the component re-render. Solution is to first slice the array and create a shallow copy, then sort.

Bad:

 filters: {
    sortedDays(days) {
      return days.sort().join(', ');
    },
  },

Good:

 filters: {
    sortedDays(days) {
      return days.slice().sort().join(', ');
    },
  },

Solution 4 - node.js

You can get this error if you call a function instead of pass a function in a vue directive. Here is an example:

I made a custom directive to load data via AJAX when a boostrap tab is displayed.

This is bad:
 v-on-show-bs-tab="getFirstPageSites()"

Here, vue appears to call the function (or rather evaluate the expression) and pass the result to the directive.

This is good:
 v-on-show-bs-tab="getFirstPageSites"

Here I am passing the function by name such that I can call it in the directive.

Solution 5 - node.js

I got this same error after making the dumb mistake of using :click in a component instead of @click

Solution 6 - node.js

In my case I was mutating an object inside a function, and I think that whenever I mutated it, it called the same function again and again (kind of a recursion). So instead of have this in the function body:

this.someProperty = myObject;

I put all the code in a new function (the function's name is totalesSimples) that return "myObject".

And in the HTML part, instead of showing it like:

{{someProperty}}

I showed it with:

{{totalesSimples()}}

This way, I was not mutating a property inside a function and showing it; I was showing the function's result.

Solution 7 - node.js

What I did wrong:

I didn't use an arrow function when using data

For example:

data() {
  state: {
     foo: 'bar'
  }
},
created() {
  bus.$on('data_change', function(data) {
    this.state = Object.assign({}, this.state, data); <-- this will cause an infinite loop
  });
}

Used an arrow function instead:

created() {
  bus.$on('data_change',(data) => {
    this.state = Object.assign({}, this.state, data);
  });
}

Thought it looked like a common mistake

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionramzi trabelsiView Question on Stackoverflow
Solution 1 - node.jsaksView Answer on Stackoverflow
Solution 2 - node.jsDecade MoonView Answer on Stackoverflow
Solution 3 - node.jsAndyView Answer on Stackoverflow
Solution 4 - node.jsJessView Answer on Stackoverflow
Solution 5 - node.jsNeil HoffView Answer on Stackoverflow
Solution 6 - node.jsLuis Cabrera BenitoView Answer on Stackoverflow
Solution 7 - node.jsglinda93View Answer on Stackoverflow