[SalesForce] Working with refreshApex in LWC

I have one wire method in JS, when it finishes processing it sets this.showSpinner = false, everything is working as expected.

@track showSpinner = true;

@wire(getApexStudyData, { objectId: '$objId' })
imperativeStudyWiring(result) {
  this.wiredStudyResult = result;

  if (result.data) {
      // assign values here 
      this.showSpinner = false

  }
}

sometimes instead of entering data on the page user enter data through data loader or x author of apttus cpq and then refreshes the page to see if the page has updated data or not.

Now instead of refreshing the page we need to create a button which will just refreshes the data to achieve the same I have created an HTML button and upon clicking it executes below method and it works as expected if the data has changed in the data base then upon clicking below button it updates the data on the page.

refreshData() {
    if (this.wiredStudyResult) {
        refreshApex(this.wiredStudyResult);
    }
}

Till now everything is coming as expected but sometimes above method takes 3 to 5 seconds to show refreshed data so while it is refreshing data we need to display a spinner just like when page renders first time, a spinner appears and once data is loaded it went off, I have tried below approaches to achieve the same.

1st approach: it refreshes the data but spinner doesn't appear.

refreshData() {
    if (this.wiredStudyResult) {
        this.showSpinner = true;
        refreshApex(this.wiredStudyResult);
        this.showSpinner = false;
    }
}

2nd approach: sometime adding timeout does the trick but here it didn't work.

 refreshData() {
        if (this.wiredStudyResult) {
            this.showSpinner = true;
            setTimeout(() => {
               refreshApex(this.wiredStudyResult);
               this.showSpinner = false;
             }, 100)
        }
    }

3rd approach: here I am not setting the this.showSpinner = false and I changed the data in the database and clicked this button and it worked as expected spinner rendered and once the refreshApex finished it went off (as showSpinner field is setting false inside the wire method), now the problem with this approach is when I don't change any thing in the database and page has updated data then upon clicking refresh button ideally it should do nothing but spinner will appear and remains there forever.
in other words if page has updated data then showSpinner = false inside the wire method doesn't work or wire method doesn't execute at all.

refreshData() {
        if (this.wiredStudyResult) {
            this.showSpinner = true;
            refreshApex(this.wiredStudyResult);
        }
    }

Can someone please help me how can I manage this.showSpinner variable accordingly with refresh apex.

please excuse if I have made any syntax error while copying and pasting the code, but trust me I have tried and tested above all the approaches in real time :).

Best Answer

The first method "does nothing" because the call is asynchronous, so from the browser's point of view, the flag effectively never changed.

The second method doesn't work for the same reason; refreshApex is still running when you set the flag back to false.

The third method fails because, as you said, the wire method only updates if there's actually new data.

The solution...

It appears that refreshApex returns a Promise, so the following code should work:

refreshData() {
    this.showSpinner = true;
    refreshApex(this.wiredStudyResult)
      .then(() => this.showSpinner = false)
      .catch(() => this.showSpinner = false);
}
Related Topic