Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js destroy a setInterval running inside a component

In my SPA made with VUE I have a component running a recursive few of setInterval functions (it's a countdown). I noticed the countdown continue in the background when I switch view to another component, but I prefer to destroy the setInterval.

I tried using a global data having the countdowns and then destroy it on destroyed hook but it doesn't work.

Here my code:

    data: function () {
        return {
            counters: ""
        }
    }),

   methods: {
     countdown(index, exp) {
        ...
          this.counters = setInterva()
        ...
        },
   },

   destroyed(){
        console.log(this.counters); // returns a progressive integer
        clearInterval(this.counters);
        console.log(this.counters); // returns same integer
        this.counters = 0;
        console.log("destroyed");
    } 

But in the console I got:

destroyed

app.js:64433 0

app.js:64398 Missing counter_1 . <--- which means counter is still running

Thanks for any suggestion!

like image 956
Uncoke Avatar asked Aug 23 '19 07:08

Uncoke


3 Answers

There might be two things happening here depending on if you are calling countdown or not:

1. countdown is not called

countdown(index, exp) needs to be defined in the created hook such as below. Furthermore, a method foo() should be bound to this interval for the expected functionality.

  created: function(){
      this.counterInterval =  setInterval(
        function()
        {
          this.foo();
        }.bind(this), 500);
    return this.foo();
  },
  destoyed: function(){
    clearInterval( this.counterInterval )
  },

2. countdown is called properly but the component is actually not getting destroyed

If the error is actually a misunderstanding on what it means to "destroy" the component, such that the component is not getting destroyed, the same code as above can be used, but a data prop of isShowing: true bounded within the JSX will solve the problems.

Just do a v-if check on isShowing and then do an event listener if the element is in view. If the element is in view, then we have isShowing===true. else, false.

like image 79
T.Woody Avatar answered Nov 01 '22 04:11

T.Woody


In vue3 destroy() and beforeDestroy() has been deprecated.

Use unmount() or beforeUnmount() instead.

beforeUnmount(){
    clearInterval(this.counters);
}
like image 39
Zagrios Avatar answered Nov 01 '22 02:11

Zagrios


You should use beforeDestroy hook instead of destroyed

For reference on vue lifecycle check out https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

like image 1
Hendry Avatar answered Nov 01 '22 04:11

Hendry