1

I have a hidden lightning component on a Lightning page that checks some data of the record and updates the record if needed. The record is a SBQQ__Quote__c record.

It mostly works, however, sometimes the record loads with cached (i.e. stale) data instead of the most recent data. Here is the code in the component:

<aura:component implements="force:hasRecordId,force:hasSObjectName,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global" controller="SBQQ_CheckLineItems">
    <!-- This is a hidden component on the SBQQ__Quote__c page used to check that GSA Line Item Descriptions comply with the rules -->

    <aura:attribute name="record" type="Object"/>
    <aura:attribute name="simpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>

    <force:recordData aura:id="recordLoader"
                      recordId="{!v.recordId}"
                      layoutType="FULL"
                      fields="SBQQ__ExpirationDate__c,Warning__c,QLE_Run__c"
                      mode="VIEW"
                      targetRecord="{!v.record}"
                      targetFields="{!v.simpleRecord}"
                      targetError="{!v.recordError}"
                      recordUpdated="{!c.doInit}"
                      />
</aura:component>

I've tried keying off of the event type, but it is just telling me it is Loaded.

var eventParams = event.getParams();
if(eventParams.changeType === "LOADED") {
   // force the reload while skipping the cache
   // this puts me in infinite loop
}

I've tried forcing a reloadRecord method and skipping the cache as documented here: https://developer.salesforce.com/docs/component-library/bundle/force:recordData/specification

The problem is this creates an infinite loop of loading. Is there anyway to detect if the load is from the cache or from the server?

Thanks,

Mike

2
  • Why you don't use Lightning:recordform instead of force:recorddata ? Commented May 8, 2019 at 2:57
  • Lightning:recordform displays on the GUI which I don't want. force:recorddata allows me to retrieve data without displaying anything which is what I want. Commented May 8, 2019 at 18:40

1 Answer 1

0

In case anyone is experiencing similar problems, I finally found a solution to the stale data issue in lightning. This is currently being tested in Summer '19 preview.

The general approach is to retrieve information both through force:recordData (which represents what is displayed to the user) and through a traditional apex call (what is in the database). If there is a difference, then stale data is being displayed and force a refresh. I use a Javascript Promise to make sure the everything is executed sequentially. This is still undergoing testing, but initial smoke testing looks promising.

In a hidden component on the lightning page, I have the code below. Hope this helps someone.

Component Code:

<aura:component implements="force:hasRecordId,force:hasSObjectName,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global" controller="SBQQ_CheckLineItems">
    <!-- This is a hidden component on the SBQQ__Quote__c page -->

    <aura:attribute name="record" type="Object"/>
    <aura:attribute name="simpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>

    <force:recordData aura:id="recordLoader"
                recordId="{!v.recordId}"
                layoutType="FULL"
                fields="SBQQ__Status__c,SAP_Priced_Backend__c"
                mode="EDIT"
                targetRecord="{!v.record}"
                targetFields="{!v.simpleRecord}"
                targetError="{!v.recordError}"
                recordUpdated="{!c.doInit}"
                />

</aura:component>

In Controller:

({
    doInit : function(component, event, helper) {
        helper.performReload(component, event, helper);
        // do other stuff here...
    }
})

In Helper:

({
    performReload: function(component, event, helper) {
        var loadedRecordSAPPriced = component.get("v.simpleRecord.SAP_Priced_Backend__c");
        var loadedRecordStatus = component.get("v.simpleRecord.SBQQ__Status__c");
        var retrieveQuoteAction = component.get("c.getQuote");
        var recId = component.get("v.recordId");
        var retrieveQuoteParams = { "qId" : recId.toString() };
        retrieveQuoteAction.setParams(retrieveQuoteParams);
        var retrieveQuotePromise = helper.executeAction(component,retrieveQuoteAction);
        retrieveQuotePromise.then (
            $A.getCallback(function(response){
                debugger;
                if (loadedRecordSAPPriced != null && loadedRecordStatus != null && (response.SAP_Priced_Backend__c != loadedRecordSAPPriced || response.SBQQ__Status__c != loadedRecordStatus))     // this indicates cached version that got loaded is different than what is in database
                {
                    component.find('recordLoader').reloadRecord(true);
                }
            })
        ).catch();
    },

    executeAction: function(cmp,action,callback) {
        return new Promise(function(resolve,reject) {
            action.setCallback(this, function(response) {
                debugger;
                var state = response.getState();
                if (state==="SUCCESS") {
                    var retVal=response.getReturnValue();
                    resolve(retVal);
                } else if (state==="ERROR") {
                    var errors = response.getError();
                    if(errors) {
                        if(errors[0]&& errors[0].message) {
                            reject(Error("Error message: " + errors[0].message));
                        }
                    } else {
                        reject(Error("Unknown error"));
                    }
                }
            });
            $A.enqueueAction(action);
        });
    }
})

In Apex Class:

    @AuraEnabled
    public static SBQQ__Quote__c getQuote(Id qId)
    {
        List<SBQQ__Quote__c> qtList = [SELECT Id, QLE_Run__c, SBQQ__ExpirationDate__c, Warning__c, SAP_Priced_Backend__c, SBQQ__Status__c FROM SBQQ__Quote__c WHERE ID =: qId LIMIT 1];
        if (qtList.size() == 0) return null;
        SBQQ__Quote__c qt = qtList[0];
        return qt;
    }

You must log in to answer this question.

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