0

I am reading a value from localStorage (in connectedCallBack) in an lwc that I have set in another lwc, it reads the value correctly and executes the logic also correctly below, problem is the global boolean variables that I set here, it shows incorrect values in another method ( a getter for active-tab-value for a lightning-tabset). Thus the incorrect tab shows for the lightning tab. I have applied multiple console logs to understand the cycle, I saw that the execution flow in connectedCallBack runs properly, then the getter of the lightning-tabset was initially showing the right values for the boolean, but the last console showed opposite values therefore the incorrect tab is showing up. I am getting confused due to the weird behaviour. Here is the code. The console logs explains the weird behaviour.

import { LightningElement, wire, track } from 'lwc';
import { NavigationMixin} from 'lightning/navigation';

export default class EcxAccountPicker extends NavigationMixin(LightningElement) {

  @track  isAccountActive = true;
  @track isMyDistrictActive = false;

connectedCallback(){   

        this.cvgj();
     
         if(this.isAccountActive) {  // this if block wont execute
            console.log('block 1');  // not showing in log which is fine
            this.fetchAccounts();
         }
         else if(this.isMyDistrictActive){ // this if block executes
            
            console.log('Block 2');   // shows in console correctly

            this.fetchDistrictData();  
         }
       
    }

 cvgj(){

        if(localStorage.getItem('fromTerritories') != null && 
    localStorage.getItem('fromTerritories') != undefined) {
            
     this.isAccountActive = false;
     this.isMyDistrictActive = true;
console.log('bool values in cvgj', this.isAccountActive, this.isMyDistrictActive);  // shows false, true  which is correct !


    }
    else{
        this.isAccountActive = true;
        this.isMyDistrictActive = false;
        

    }
    }

}

    get activeTabVal(){
 
    localStorage.removeItem('fromTerritories');

// the below console shows true,false which is opposite of what should happen

    console.log('boolean values in activeTabVal', this.isAccountActive, this.isMyDistrictActive);
    return this.isAccountActive?'Accounts': this.isMyDistrictActive?'My District': '';


    }

    handleTabActive(event){

        let tabName = event.target.value;
        if(tabName == 'Accounts'){
 this.isAccountActive = true;
            this.fetchAccounts();

        }  else if(tabName == 'My District') {
 this.isMyDistrictActive = true;
            this.fetchDistrictData();
}


}


the template

<template>

 <lightning-tabset active-tab-value={activeTabVal}>
 <lightning-tab label={labels.accs} value='Accounts' onactive={handleTabActive} > 
 <template lwc:if ={accountsData.length}>
<!-- Datatable code here based on accountdata -->

</template>
</lightning-tab>

 <lightning-tab label={labels.district} value='My District' onactive={handleTabActive} > 
 <template lwc:if ={districtData.length}>

<!-- Datatable code here based on districtData -->


  </template>

</lightning-tab>


 </lightning-tabset>



</template>

so basically what I want is if the localstorage being read has a value then the district tab should be visible and the appropriate districtData should be shown. If Normal cases the Accounts tab with accounts data should be shown, but due to the incorrect boolean variables at get activeTabVal the incorrect tab is showing.

** EDIT ** I tried the below solution, I had avoided a getter and now used it as normal property in JS, now correct tab appears but the datatable does not render. enter image description here

2
  • @sfdcfox would be great to have your suggestion here
    – Amax1
    Commented Jul 20, 2023 at 18:45
  • It's sfdcfox (for now).
    – sfdcfox
    Commented Jul 20, 2023 at 18:48

1 Answer 1

0

First of all, track is redundant in your use case. You only need this when mutating objects (e.g. an Array or Object changes values).

Second, what's happening here is that the getter is being called twice. It is first called after connectedCallback completes in order to initially render the template, and then a second time after fetchAccounts or fetchDistrictData loads the data. Because the getter has a side effect, this causes the behavior you're seeing.

Do not cause side effects (e.g. removing something from localStorage) in a getter without careful consideration of what will happen if the function is called more than once, or even possibly not at all. Instead, just define a activeTabValue property, and set that value at the appropriate time (e.g. as part of calling fetchAccounts or fetchDistrictData).

6
  • Im coming back to this lwc from another lwc, so I had applied debug logs to see that connectedCallBack is executed first, I need to set the default value of the lightning tab right then instead of at fetchAccounts or fetchDistrit methods since those tabs become active during onActive event of the tabs, so there are 2 cases, once when the component is loading initially ( then Accounts will be default) and the other is when it comes back from that specific lwc (district will be default tab). So the property, that can be set to either Accounts or District at ConnectedCallBack itself right?
    – Amax1
    Commented Jul 20, 2023 at 19:15
  • Also when you said the getter is called the second time, is it due to the fetchAccounts or fetchDistrict being called from handletabActive? because handleTabActive gets executed only on the onActive event of the tabs, but the fetchAccounts and fetchDistrictData is called in connectedCallBack as well, which one did you mean during the second instance?
    – Amax1
    Commented Jul 20, 2023 at 19:21
  • @Amax1 connectedCallback calls either fetchAccounts or fetchDistrictData, and then continues synchronously. After it completes, render and renderedCallback are called. Part of the render cycle is to call all getters. This is the first call. Next, fetchAccounts or fetchDistrictData will complete, presumably setting some data in the component controller. This will trigger another render and renderedCallback cycle, during which the getters will run once again. The solution is to clear localStorage in connectedCallback and set activeTab at that time.
    – sfdcfox
    Commented Jul 20, 2023 at 19:28
  • the localstorage can be cleared right before the connectedCallBack ends correct? It doesnt need to be in the conditional if statements, but the activetab value will be set in the if(this.isAccountActive) or if(this.isDistrictActive) depending on the appropriate boolean tracker?
    – Amax1
    Commented Jul 20, 2023 at 19:34
  • @Amax1 Yes, you can avoid the problem by using a standard property and setting it in connectedCallback, then clear the localStorage.
    – sfdcfox
    Commented Jul 20, 2023 at 19:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .