9

Please note that this is not duplicate of LWC Force Refresh Wire getRecord - this question and answer specifically speaks about changes in front-end/UI and capturing that in front-end BUT LDS cannot listen to database changes to record and so we need to manually refresh LDS record cache.

Question:

According to documentation of refreshApex, if we know that record has been updated in database, we can invoke refreshApex to re-invoke and refresh the cached response of Apex method response.

But for wired service getRecord, there is no such method to manually refresh the cache and it refreshes the cache only after 30 seconds from last fetching the record ( - if invoked within or after 30 seconds). If I know that the record has been updated in the database through some backend transaction (like workflow), how can we manually refresh cache of getRecord?

13

To make refreshApex clear the client-side cache it is necessary to capture and store the entire result from the getRecord wire. In this case you cannot define your handler to accept an anonymous object with data and error properties.

You need to do something like the following. First add a private property to hold the result:

_getRecordResponse;

Then update the handling of the getRecord wire response from something like:

@wire(getRecord, {...})
receiveRecord({error, data}) {
    ...
}

to:

@wire(getRecord, {...})
receiveRecord(response) {
    this._getRecordResponse = response;
    let error = response && response.error;
    let data = response && response.data;
    ...
}

Now that you have the _getRecordResponse, you can force the record to be reloaded by calling:

refreshApex(this._getRecordResponse);
2
  • 1
    Worth also noting you might be able to listen for changes in the backend using the Emp service - basically using streaming API and a change event. – Phil W Sep 26 '19 at 9:27
  • 1
    Thanks Phil!, when I tried this implementation before, I was not getting log and so thought its not refreshing. I answered for that part below – salesforce-sas Sep 26 '19 at 10:04
3

Extending answer from @Phil W,

For below Sample LWC Js:

@api recordId = '00128000009j45tAAA';
@track wiredAccount;

fields = [ACCOUNT_NAME_FIELD, ACCOUNT_DESCRIPTION_FIELD];

@wire(getRecord, { recordId: '$recordId', fields: '$fields' })
fetchAcc(response) {
    console.log('Account => ', JSON.stringify(response));
    this.wiredAccount = response;
}

refreshWire() {
    refreshApex(this.wiredAccount);
}

Although we invoke refreshWire, the wired method fetchAcc will be invoked ONLY if new record and UI record in this.wiredAccount are not same and consecutively see the console log. If the new record is same as UI record this.wiredAccount, the method fetchAcc will not be invoked (even after 30 seconds) and we will not see any console log. Finally, refreshApex should have been named refreshWire as it not just updates apex method response but also wired service response.

4
  • refreshApex is, I would presume, called refreshApex because both imperative and wired calls are fundamentally both just calling a (cacheable) AuraEnabled Apex method. The difference with a wired service is that there is client-side logic for handling caching (and for detecting changes to wired "reactive" parameters for re-invocation). – Phil W Sep 26 '19 at 10:25
  • @PhilW So, you mean getRecord is internally apex method in lightning namespace ? – salesforce-sas Sep 26 '19 at 10:31
  • Yeah, I would think so. It seems like Salesforce is generally pretty good at using its own plumbing to implement stuff. Obviously I can't guarantee this since I've not seen the code, but it makes sense to do it this way. – Phil W Sep 26 '19 at 10:49
  • crap.. this is good.. I was doing eval('$A.force.refreshView`) – Pranay Jaiswal Sep 26 '19 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.