You need to sign in to do that
Don't have an account?
GCW Labs
LWC renderedCallback() inconsistency
In LWC I'm rebuilding an array based on some filter parameters, and depending on the amount of data there is some lag. For example, set a filter, there is a delay of a couple seconds, then the filter value changes and the new list displays. I'm trying to show a spinner in these scenarios, but I need to hide the spinner after the array rerenders. There seems to be a catch-22 in how the renderedCallback() function works. Here are some examples. The HTML is always the same.
HTML
<template if:true={showSpinner}>
<div class="slds-grid slds-grid_vertical-align-center slds-align_absolute-center" style="height:100%;">
<lightning-spinner class="slds-is-relative"
alternative-text="Loading"
size="medium"
variant="brand">
</lightning-spinner>
</div>
</template>
<template if:false={showSpinner}>
<template for:each={filteredRecords} for:item="rec">
<!--display rec info here-->
</template>
</template>
Example 1
allRecords = [];
filteredRecords = [];
showSpinner = false;
connectedCallback() {
// set allRecords here;
}
renderedCallback() {
// renderedCallback runs once after a couple of seconds delay
}
handleFilterChange(event) {
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filteredRecords = tempRecords;
}
Example 2
allRecords = [];
filteredRecords = [];
showSpinner = false;
filterRender = false;
connectedCallback() {
// set allRecords here
}
renderedCallback() {
// renderedCallback runs twice, once immediately which turns off the spinner, and then again as in the first example after a couple of seconds when the list rerenders
this.showSpinner = false;
}
handleFilterChange(event) {
this.showSpinner = true;
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filteredRecords = tempRecords;
}
Example 3
allRecords = [];
filteredRecords = [];
showSpinner = false;
filterRender = false;
connectedCallback() {
// set allRecords here
}
renderedCallback() {
// renderedCallback runs twice again, but in the first run filterRender is already set to true, so again it turns off the spinner right away
if (this.filterRender === true) {
this.showSpinner = false;
this.filterRender = false;
}
}
handleFilterChange(event) {
this.showSpinner = true;
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filterRender = true;
this.filteredRecords = tempRecords;
}
When renderedCallback runs seems to be arbitrary. When I’m not setting the spinner to false in renderedCallback() it runs once after a few seconds. If I do set the spinner, it runs twice but there is no way to flag the second run as the one in which the spinner should be disabled.
Note that if in all instances, the filteredList is already rebuilt, it’s just a delay as it’s rendered in the HTML file. So I can’t even check the status of the list to see if the spinner should be disabled.
HTML
<template if:true={showSpinner}>
<div class="slds-grid slds-grid_vertical-align-center slds-align_absolute-center" style="height:100%;">
<lightning-spinner class="slds-is-relative"
alternative-text="Loading"
size="medium"
variant="brand">
</lightning-spinner>
</div>
</template>
<template if:false={showSpinner}>
<template for:each={filteredRecords} for:item="rec">
<!--display rec info here-->
</template>
</template>
Example 1
allRecords = [];
filteredRecords = [];
showSpinner = false;
connectedCallback() {
// set allRecords here;
}
renderedCallback() {
// renderedCallback runs once after a couple of seconds delay
}
handleFilterChange(event) {
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filteredRecords = tempRecords;
}
Example 2
allRecords = [];
filteredRecords = [];
showSpinner = false;
filterRender = false;
connectedCallback() {
// set allRecords here
}
renderedCallback() {
// renderedCallback runs twice, once immediately which turns off the spinner, and then again as in the first example after a couple of seconds when the list rerenders
this.showSpinner = false;
}
handleFilterChange(event) {
this.showSpinner = true;
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filteredRecords = tempRecords;
}
Example 3
allRecords = [];
filteredRecords = [];
showSpinner = false;
filterRender = false;
connectedCallback() {
// set allRecords here
}
renderedCallback() {
// renderedCallback runs twice again, but in the first run filterRender is already set to true, so again it turns off the spinner right away
if (this.filterRender === true) {
this.showSpinner = false;
this.filterRender = false;
}
}
handleFilterChange(event) {
this.showSpinner = true;
let filter = event.target.value;
let tempRecords = [];
for (let rec of allRecords) {
if (rec.field === filter) {
tempRecords.push(rec);
}
}
this.filterRender = true;
this.filteredRecords = tempRecords;
}
When renderedCallback runs seems to be arbitrary. When I’m not setting the spinner to false in renderedCallback() it runs once after a few seconds. If I do set the spinner, it runs twice but there is no way to flag the second run as the one in which the spinner should be disabled.
Note that if in all instances, the filteredList is already rebuilt, it’s just a delay as it’s rendered in the HTML file. So I can’t even check the status of the list to see if the spinner should be disabled.
Check this once.