LWC property is not reactive
Classic... Javascript is quite weird, this
changes quite frequently with respect to the context.
in setInterval
, this
does not refer to your binded variables, but something else.
You have to pass this
as some param in setInterval
import { LightningElement, api, track, wire } from 'lwc';
export default class LoadContact extends LightningElement {
@track closedt ='2019-08-09';
@track daysFinal =0;
@track hoursFinal;
@track minutesFinal;
@track secondsFinal;
timeIntervalInstance;
totalMilliseconds = 0;
datecounter(){
let oppCloseDt = new Date(this.closedt);
let months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
let monthName = months[oppCloseDt.getMonth()];
let dateNumber = oppCloseDt.getDate();
let yearNumber = oppCloseDt.getFullYear();
let closeDateVar = monthName+' '+dateNumber+' '+yearNumber;
let opptCloseDate = new Date( closeDateVar+" 00:00:00 ");
let myparam = this;
// eslint-disable-next-line @lwc/lwc/no-async-operation
setInterval(function() {
let opptyCloseDate = new Date( closeDateVar+" 00:00:00 ");
window.console.log('opptyCloseDate...' + opptyCloseDate);
let nowdate = new Date();
let timeDiff = opptyCloseDate.getTime()- nowdate.getTime();
let seconds=Math.floor(timeDiff/1000); // seconds
let minutes=Math.floor(seconds/60); //minute
let hours=Math.floor(minutes/60); //hours
let days=Math.floor(hours/24); //days
hours %=24;
minutes %=60;
seconds %=60;
myparam.hoursFinal =hours;
myparam.daysFinal =days;
myparam.minutesFinal =minutes;
myparam.secondsFinal =seconds;
myparam.daysFinal =null;
myparam.daysFinal = days;
window.console.log('this.hoursFinal...' + myparam.hoursFinal);
window.console.log('this.daysFinal...' + myparam.daysFinal);
}, 5000 , myparam);
}
}
Playground Link : https://developer.salesforce.com/docs/component-library/tools/playground/6dm391HNp/2/edit
Src: https://stackoverflow.com/questions/7890685/referencing-this-inside-setinterval-settimeout-within-object-prototype-methods/7890978
This pitfall is quite common for salesforce developers working on Javascript. Set-Interval actually changes the context of this to window as functions like setInterval, setTimeout etc are async functions and hence these functions run after the main thread has finished processing. This can be addressed by any of 2 options:
- Lexical Scoping - old fashioned (pls do a google search for understanding)
- Arrow functions - Modern javascript. (PFB)
Just change the callback function from:
setInterval(function(){}, 500);
To
setInterval(() => {}, 500);
For simple understanding, Arrow functions don't have their own scope because of which it takes the scope of parent object.
There are many other advantages of arrow functions. Further read: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions