@ngrx/store with InfiniteScroll, Pull-To-Refresh and Loading Indicators

I’ve only really been looking at @ngrx/store the last couple of weeks but I really love it and have converted my current app to use it. One thing I am not sure of is a good pattern for handling loading spinners, infinite scrollers and pull to refresh refreshers.

Let’s say I have a bunch of view components and some of them might have an initial loading spinner and then some may also use infinite scroll for getting the data in a paginated way and then many of them will also have the pull to refresh component embedded in them too.

At the moment, I am dealing with these when I subscribe to the store and get the data i.e I might have something like this (in a component that uses all three)

.subscribe((store:MyStore) => {

// hide spinner or complete refresher
if(!this.refresher) this.displaySpinner = false;

if (this.refresher) {
    this.refresher = null;

// manage infinite scroll
if (this.infiniteScroller) {
    if (store.items.length === 0) {
       this.infiniteScroller.enabled = false;

this.items = [...this.items,...store.items]


I’d like to remove the block of code that handles the spinner, refresher and infinite scroller and have this automatically handled somehow by the store and therefore shared across all components. I think I can handle a standard loading spinner by having a boolean loading value in the store and then isLoading and doneLoading actions (and calling them via the @effects methods). But I’m not really sure about the refresher and infinite scroller as these are more linked to the actual component.

Has anyone got a good best practice pattern for this sort of thing? (or is what I am doing an ok way of handling it?

1 Like

Thanks for the tip! I just started with ngrx and got stuck on the logic for how to handle this. I’m used to the more declarative React, so how to do handle this imperatively threw me. This setup worked well for me. The only difference is I have a selector for the loading state specifically so that I’m not subscribed to all state changes.

this.store.select(selectIsLoading).subscribe(isLoading => {
  if (this.refresher && !isLoading) this.refresher.complete();