In this article, we will discuss a common use case of Lightning Web Component. Lightning Data Service is a great tool allowing you to use the same cache as Lightning Experience, bringing better performances and less code to write.
Using Lightning Base Components like lightning-record-form
or using out-of-the-box getRecord
or createRecord
methods will make record editing much easier. Thanks to the shared cache from Lightning Data Service, updating a record from your custom component will automatically update the standard record page, and vice versa.
Still, you’ll most likely end up at some point using Apex, if your use case is a little bit more complex than that, for instance involving a web service or multi-record editing.
Saving the current record from Apex have one drawback:
It’s done outside of the eye of Lightning Data Service, and thus will not refresh the page correctly. Your component may display the correct updated value, but Salesforce’s standard record page will still display the old one.
So how do you ask to your record page to force update itself ? Well, Aura had a nice mechanism for it, force:refreshView. After the record was updated from Apex, you could just call it to ask Salesforce to refresh its own cache:
But alas, there was no such event in LWC 😩
I’ve seen several workarounds, from calling force:refreshView
from LWC via a small hack, to saving a second time the record after Apex update was done, this time via Lightning Data Service so that the cache would update. Obviously, none of these methods were neither optimal nor recommended.
So how can we do it properly?
Enters getRecordNotifyChange
Starting Winter ’21, there is a new function in town!
Using it is as simple as what we’ve been used to in Aura. You’ll just need to import it (import { getRecordNotifyChange } from 'lightning/uiRecordApi';
), and then call it with a list of record Ids (getRecordNotifyChange([{recordId: this.recordId}]);
).
Full sample code looks like this :
Note that this new function is even more powerful than the old force:refreshView
event, because you can not only refresh the current record page, but also pass a list of all record Ids you’ve updated. This will prevent navigating to other records with cache being not up-to-date, and thus invalid data displayed, and frustrated users.
This implies one change though :
force:refreshView
was refreshing the whole page, whereas getRecordNotifyChange()
is only refreshing the records you ask him to refresh. So if your Apex code is for instance updated the current Account, but also some child Contacts, you may have to pass to getRecordNotifyChange()
all the Ids updated by your Apex method.
This makes sense
When you think about it, everything around LWC is done with performance in mind. So updating only a subset of records instead of a whole page (which may includes several dozen of records when you think of related lists) will always be faster.
Looking at a method updating an Account and its related Contacts. You would need to return the list of updated Ids:
And then just pass the list of these updated records to getRecordNotifyChange()
:
So it’s a little bit of overhead work compared to force:refreshView
if you’re updating several records, but that’s for the sake of performance. And you don’t want anyone to tell you that your custom component is slow, right ?
One part where getRecordNotifyChange()
isn’t at parity with force:refreshView
is that it won’t bring new records to the local cache. What does that mean ? Let’s say you create new Contacts from an Account page, force:refreshView
would refresh the whole page, and new Contacts would appear in the related list. getRecordNotifyChange()
however can refresh existing Contacts in the related list, but will not bring new Contacts to the page.
Hopefully, this gap will be closed in a future release.
You can learn more in the Lightning web components developer guide.
So no time to lose, go update your existing Lightning web components now! And if you want to learn more, read our article about Lightning Migration for Admins! 💻