I have a parent LWC with a list of records and a child LWC which allows the user to perform actions on the record.
The child uses dispatchEvent
and CustomEvent
to notify the parent after changes have been made to the record, so that the parent can refresh the list of records.
Unfortunately, refreshApex
in the parent is not always working...
Here is the code.....
parent component
<template>
// contains a list of records, removed for brevity
<c-child-record-detail onback={handleBack} record-id={recordId}></c-child-record-detail>
</template>
parent JavaScript
import { LightningElement, wire } from "lwc";
import { refreshApex } from "@salesforce/apex";
import getRecords from "@salesforce/apex/MyController.getRecords";
export default class MyLWC extends LightningElement {
records;
wiredResult;
records; // used to render
recordList; // used to store the original set from the server
filterValue = "";
recordId;
@wire(getRecords) wiredRecords(value) {
this.wiredResult = value;
const { data, error } = value;
if (data) {
this.error = null;
this.recordList = data;
this.filterList();
} else if (error) { ... }
}
refreshList() {
return refreshApex(this.wiredResult);
}
handleBack() {
this.recordId = null;
this.refreshList();
}
handleFilterChange(event) {
this.filterValue = event.detail.value;
this.filterList();
}
filterList() {
switch (this.filterValue) {
case "Status1":
this.records = this.recordList.reduce(this.exampleReducer, []);
break;
// many other cases removed for brevity
}
}
exampleReducer = (accumulator, currentValue) => {
if (currentValue.Status__c === "example") {
accumulator.push(currentValue);
return accumulator;
}
return accumulator;
};
// many other reducers, removed for brevity
handleRowClick(event) {
this.recordId = event.currentTarget.dataset.recordId;
}
}
I've tried very hard to reduce the code example down without losing its essence.
You will notice that I am doing client side filtering using reduce
.
The c-child-record-detail
component is reasonably complex, but the problem related to two buttons which are used to finish looking at the record, so we can go back to the list.
child component
child button A JavaScript
handleButtonAClick() {
updateAsSomeSubStatus({ recordId: this.recordId}).then(result => {
if (result === true) {
this.backToList();
}
}).catch(error => this.handleError(error));
}
child button A Apex
@AuraEnabled
public static Boolean updateAsSomeSubStatus(Id recordId) {
try {
Opportunity record = new Opportunity(Id = recordId);
record.Sub_Status__c = "SomeSubStatus";
update record;
return true;
} catch (Exception cause) {
throw AuraHandledExceptionFactory.create(cause);
}
}
child button B JavaScript
handleButtonBClick() {
updateAsStatusAndSubStatus({ recordId: this.recordId}).then(result => {
if (result === true) {
this.backToList();
}
}).catch(error => this.handleError(error));
}
child button B Apex
@AuraEnabled
public static Boolean updateAsStatusAndSubStatus(Id recordId) {
try {
Opportunity record = new Opportunity(Id = recordId);
record.StageName = "SomeStageName";
record.Sub_Status__c = null;
update record;
return true;
} catch (Exception cause) {
throw AuraHandledExceptionFactory.create(cause);
}
}
Both buttons work, and the record is updated successfully.
Both buttons return a result
of true
;
Both buttons call the backToList
JavaScript method
backToList() {
this.dispatchEvent(new CustomEvent("back"));
}
The List only only refreshes correctly for button A.
I also have a refresh button on the list which calls refreshApex
and no matter how many times I click on it, it does not get the refresh records.
I have to do a hard refresh of the page!
Question
- What on earth is going on?
- Am I going crazy? :o)
- How can I fix it such that
refreshApex
consistently works?
- What other ways are there to clear the cache such that
wire
will re-fire?