title: Get only distinct values from an ngrx store selector
body: <p>I have a function which checks whether a grid has loaded or not and if not it triggers the loading. But currently this ends up firing several times for the same <code>Loaded</code> value so it will call the relevant action multiple times. I was under the impression that store selectors emit by default only distinct (changed) values?</p>
  
  <p>My function</p>
  
  <pre><code>private gridLoaded(filters: FilteredListingInput): Observable&lt;boolean&gt; {
      return this.settings.states.Loaded.pipe(
          tap(loaded =&gt; {
              this.logService.debug(
                  `Grid ID=&lt;${
                      this.settings.id
                  }&gt; this.settings.states.Loaded state = ${loaded}`
              );
  
              // Now we get duplicate firings of this action.
              if (!loaded) {
                  this.logService.debug(
                      `Grid Id=&lt;${
                          this.settings.id
                      }&gt; Dispatching action this.settings.stateActions.Read`
                  );
  
                  this.store.dispatch(
                      new this.settings.stateActions.Read(filters)
                  );
              }
          }),
          filter(loaded =&gt; loaded),
          take(1)
      );
  }
  </code></pre>
  
  <p><code>this.settings.states.Loaded</code> is selector from NgRx store.
  The logging output I get looks like this:</p>
  
  <pre><code>Grid ID=&lt;grid-reviewItem&gt; this.settings.states.Loaded state = false {ignoreIntercept: true}
  Grid Id=&lt;grid-reviewItem&gt; Dispatching action this.settings.stateActions.Read {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; this.settings.states.Loaded state = true {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; Calling FilterClientSide action. Loaded=true {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; this.settings.states.Loaded state = true {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; Calling FilterClientSide action. Loaded=true {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; this.settings.states.Loaded state = true {ignoreIntercept: true}
  Grid ID=&lt;grid-reviewItem&gt; Calling FilterClientSide action. Loaded=true {ignoreIntercept: true}
  </code></pre>
  
  <p>How can I make sure that the relevant actions are triggered only once?</p>
  
  <p><strong>Edit - updates</strong></p>
  
  <p>Selector code:</p>
  
  <pre><code>export const getReviewItemsLoaded = createSelector(
      getReviewItemState,
      fromReviewItems.getReviewItemsLoaded
  );
  
  export const getReviewItemState = createSelector(
      fromFeature.getForecastState,
      (state: fromFeature.ForecastState) =&gt; {
          return state.reviewItems;
      }
  );
  
  export const getReviewItemsLoaded = (state: GridNgrxState&lt;ReviewItemListDto&gt;) =&gt;
      state.loaded;
  
  export interface GridNgrxState&lt;TItemListDto&gt; {
      allItems: TItemListDto[];
      filteredItems: TItemListDto[];
      totalCount: number;
      filters: FilteredListingInput;
      loaded: boolean;
      loading: boolean;
      selectedItems: TItemListDto[];
  }
  </code></pre>
  
  <p>As you can see we are just getting the <code>state.loaded</code> property, it's a trivial selector.</p>
  
  <p><strong>Reducers</strong> that change the <code>loading</code> property:</p>
  
  <pre><code>export function loadItemsSuccessReducer(state: any, action: GridAction) {
      const data = action.payload;
  
      return {
          ...state,
          loading: false,
          loaded: true,
          totalCount: data.totalCount ? data.totalCount : data.items.length,
          allItems: data.items
      };
  }
  
  export function loadItemsReducer(state: any, action: GridAction) {
      return {
          ...state,
          loading: true,
          filters: action.payload
      };
  }
  
  export function loadItemsFailReducer(state: any, action: GridAction) {
      return {
          ...state,
          loading: false,
          loaded: false
      };
  }
  </code></pre>
  
  <p><strong>Actions</strong></p>
  
  <pre><code>export class LoadReviewItemsAction implements Action {
      readonly type = LOAD_REVIEWITEMS;
      constructor(public payload?: FilteredListingInput) {}
  }
  
  export class LoadReviewItemsFailAction implements Action {
      readonly type = LOAD_REVIEWITEMS_FAIL;
      constructor(public payload: any) {}
  }
  
  export class LoadReviewItemsSuccessAction implements Action {
      readonly type = LOAD_REVIEWITEMS_SUCCESS;
      constructor(public payload: PagedResultDtoOfReviewItemListDto) {}
  </code></pre>
  
  <p><strong>Effects</strong></p>
  
  <pre><code>export class ReviewItemsEffects {
      constructor(
          private actions$: Actions,
          private reviewItemApi: ReviewItemApi
      ) {}
  
      @Effect()
      loadReviewItems$ = this.actions$
          .ofType(reviewItemActions.LOAD_REVIEWITEMS)
          .pipe(
              switchMap((action: reviewItemActions.LoadReviewItemsAction) =&gt; {
                  return this.getDataFromApi(action.payload);
              })
          );
  
      /**
       * Retrieves and filters data from API
       */
      private getDataFromApi(filters: FilteredListingInput) {
          return this.reviewItemApi.getReviewItems(filters || {}).pipe(
              map(
                  reviewItems =&gt;
                      new reviewItemActions.LoadReviewItemsSuccessAction(
                          reviewItems
                      )
              ),
              catchError(error =&gt;
                  of(new reviewItemActions.LoadReviewItemsFailAction(error))
              )
          );
      }
  }
  </code></pre>