[SalesForce] LWC property is not reactive

I am working on simple LWC. I can see that values are changing in the console, but property value is not changing in the component.

I tested the same thing in the Playground too, I see the same issue there also.

HTML:

<template>
    <lightning-card title="Days Left" icon-name="standard:record">
            <div class="slds-m-around_medium">
                    <div style="background: white;padding: 20px;border-radius: 6px;">
                            <div style="font-size: 20px;text-align:center;">{daysFinal}</div>
                            <lightning-button label="Start" onclick={datecounter} style="margin-left: 145px;"></lightning-button>
                    </div>
            </div>
        </lightning-card>
</template>

JS:

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 ");

        // eslint-disable-next-line @lwc/lwc/no-async-operation
        this.timeIntervalInstance = 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;   
           
             this.hoursFinal =hours;
             this.daysFinal =days;
             this.minutesFinal =minutes;
             this.secondsFinal =seconds;

             window.console.log('this.hoursFinal...' + this.hoursFinal);
             window.console.log('this.daysFinal...' + this.daysFinal);

         
            
        }, 5000);
    }

   
}

Playground:
https://developer.salesforce.com/docs/component-library/tools/playground/6dm391HNp/1/edit

enter image description here

Best Answer

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

JS

Related Topic