How setInterval is bad and a way to make your life better in LWC SalesForce (Link to working example below)
Let’s implement a counter in plane LWC component.
Say your counter runs from 0 to a specific given value.
And you have to make an animation type thingy to show it.
A way that you would make is as follows
<template>
<div class="app slds-p-around_x-large">
{count}
</div>
</template>
This would be the HTML of your component
Lets look at the JS
import { LightningElement, track } from 'lwc';
export default class App extends LightningElement {
@track count = 0;
@track percentage = 99;
connectedCallback() {
var intervalID = setInterval(function (){
this.count++;
if (this.count === this.percentage) {
clearInterval(intervalID);
}
},10);
}
}
So the setInterval would be lauched as soon as the connectedCallback lifecycle would fire.
The anonymous function would the fire for each — — 10 ms
which would increment the count value by one on each of those calls.
But here’s the catch, setInterval runs on different browser subthread thingy…
that is it doesn’t maintain context of what happens after.
Take this code for eg.
var count = 0;
var intervalID = setInterval(function (){
this.count++;
console.log(this.count); // prints number from 0 to percentage
if (this.count === this.percentage) {
clearInterval(intervalID);
}
},10)
console.log(this.count); // prints 0
The second console prints ‘0'
Which explains the fact that context is not maintained.
To make that happenm we bind the context to each anonymous function call that is made.
Just use
.bind(this) // 'this' is the context
So the JS becomes — —
import { LightningElement, track } from 'lwc';
export default class App extends LightningElement {
@track count = 0;
@track percentage = 99;
connectedCallback() {
var intervalID = setInterval(function (){
this.count++;
if (this.count === this.percentage) {
clearInterval(intervalID);
}
}.bind(this),10);
}
}
Working example in LWC web.components playground