LWC Caching Issue – How to Resolve Lightning Web Components Cache Problems

lightning-web-components

(1) I have a Lightning Component Tab on which sits a Lightning Web Component.

(2) I navigate to the tab WITH CONTEXT using the NavigationMixin from other LWC components elsewhere in the application.

(3) So the URL when I navigate to the tab/lwc looks like this:

 https://revdev1-dev-ed.lightning.force.com/lightning/n/Freight_Plan_Console?c__loadId=a0r1U00000600mNQAQ

Note the context parameter c__loadId. This value of course changes based on the Load (page) I am coming from.

Here is my issue:

(1) The first time the tab is navigated to everything works fine — The constructor, connectedCallback and @wire functions all execute and build the component. I am able to capture the URL parameters and act on them.

(2) However, subsequent navigation to the tab with a different load context does not work. The LWC is cached somewhere and so the functions above are not re-invoked.

(3) This is a problem as the URL context parameter has changed and I need to execute logic to deal with the change.

(4) Note that if I navigate around a lot or browser-refresh a page the LWC will rebuild itself correctly. But of course we cannot rely on that.

Another way to pose the question: When you navigate away from and then back to a Tab with an LWC on it, what hook can I use to execute code each time the LWC/tab is returned to?

Another way to pose the question: How do I guarantee an LWC is rebuilt each time it is navigated to?

Thanks!

Adding navigation code to LWC Tab:

addFreightPlanHandler() {

    let namespace = LightningUtil.getNamespace();
    let cnamespace = namespace ? namespace : 'c__';
    let state = {};
    state[cnamespace + 'loadId'] = this.load.Id.value;

    this[NavigationMixin.Navigate]({ type: 'standard__navItemPage', 
                                     attributes: { apiName: namespace + 'Freight_Plan_Console' },
                                     state: state });                
}

Adding first part of LWC that we are navigating to. Nothing unique about it that I am aware of:

    <template>
        <lightning-layout multiple-rows="false">
            <!-- FILTER/TEMPLATE PANEL -->
            <template if:true={showFilterTemplatePanel}>
                <lightning-layout-item size="3">
                    <div class="slds-card">
                        <div class="panelSpacer">
    .....

Best Answer

We had a similar cache issue in the past and managed to resolve it using @wire(CurrentPageReference) and getter/setter methods instead of connectedCallback. [as @nbrown pointed out in the comments]

Reference docs :

The connectedCallback() hook is invoked with the initial properties passed to the component. If a component derives its internal state from the properties, it's better to write the logic in a setter than in connectedCallback()

@wire(CurrentPageReference) captures the updated parameter state each time the page is loaded, then you can invoke your custom logic based on the new state parameter value.

Here's some sample code to get you started using CurrentPageReference

LWC componnent tab

HTML

<template>
    <div class="slds-grid slds-theme_default slds-box">
        <div class="slds-col slds-size_4-of-12">
            <h2 class="slds-text-heading_small slds-var-m-bottom_medium">
                Load Id : <code> {loadId}</code> 
            </h2>
        </div>
        <div class="slds-col slds-size_8-of-12" if:true={objectApiName}>
            <lightning-record-view-form
                object-api-name={objectApiName}
                record-id={loadId}>
            <div class="slds-box">
                <lightning-output-field field-name="Name"> </lightning-output-field>
            </div>
            </lightning-record-view-form>
        </div>
    </div>
</template>

JS

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

export default class LwcCustomTab extends NavigationMixin(LightningElement) {
    currentPageReference;
    @api loadId;
    @api objectApiName;

    @wire(CurrentPageReference)
    getCurrentPageReference(currentPageReference) {
        this.currentPageReference = currentPageReference;
        //show spinner if processing is long
        new Promise(
            (resolve, reject) => {
            setTimeout(() => {
                if(this.currentPageReference){
                    this.loadId = this.currentPageReference.state.c__loadId 
                                ? this.currentPageReference.state.c__loadId : null;
                    this.objectApiName = this.currentPageReference.state.c__objectApiName 
                                ? this.currentPageReference.state.c__objectApiName : null;
                    //perform additional logic with new loadId
                    resolve();
                }
            }, 0);
            })                
            .catch((error) => {
                console.error(JSON.stringify(error));
            })
            .finally(() => {
                // disable a spinner if applicable
            }); 
    }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

LWC redirecting to custom tab

HTML

<template>
    <div class="slds-grid slds-theme_default slds-box">
        <div class="slds-col"></div>
        <div class="slds-col">
            <lightning-button label="Redirect To Tab" variant="brand" 
                onclick={navigateToCustomTab} ></lightning-button>
        </div>
    </div>
</template>

JS

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

export default class LwcNavigateToTab extends NavigationMixin(LightningElement) {

    @api loadId;
    @api recordId;
    @api objectApiName;

    navigateToCustomTab(){
        this[NavigationMixin.Navigate]({
            type: 'standard__navItemPage',
            attributes: {
                apiName: 'LWC_Custom_Tab'
            },
            state: {
                c__loadId : this.recordId ? this.recordId : this.loadId,
                c__objectApiName : this.objectApiName
            }
        });
    }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage,lightning__AppPage,lightning__HomePage">
            <property name="loadId" label="Custom Load Id" type="String" />
            <property name="objectApiName" label="Object API Name" type="String" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>