Search code examples
angulartypescriptrxjsngrx

How to avoid unnecessary API call when working with NgRx


I have an application with 2 menu item; Teams, Players. Whenever I toggle between them, I have to unnecessary api call even though I have the data in store.

Below is the effects file: //auth.effects.ts

loadTeams$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(AuthActions.loadTeams),
      switchMap((action) =>
        this.apiService.teams$.pipe(
          tap(() => console.log('get teams request')),
          map((teams: Team[]) => AuthActions.loadTeamsSuccess({ teams })),
          catchError((error) => {
            console.log('err', error);
            return of(AuthActions.loadFailure({ error }));
          })
        )
      )
    );
  });

Below is the component from which I make api call

teams-list.component.ts

export class TeamsListComponent implements OnInit {
  loading$?: Observable<boolean>;
  error$?: Observable<string>;
  teams$?: Observable<Team[]>;
  retrySubject$ = new BehaviorSubject<boolean>(true);

  constructor(private store: Store<State>) {}

  ngOnInit(): void {
    this.store.dispatch(loadTeams());
    this.teams$ = this.store.select(getTeams);
    this.error$ = this.store.select(getError);
    this.loading$ = this.store.select(getLoading);
  }

  fetchRetry() {
    this.retrySubject$.next(false);
  }
}

This line in ngOnInit cause unnecessary api call. this.teams$ = this.store.select(getTeams);

How can I prevent it so that it makes the api call one time when initializing the app?


Solution

  • loadTeams$ = createEffect(() => {
        return this.actions$.pipe(
          ofType(AuthActions.loadTeams),
          // read the actions$ for an load success event
          withLatestFrom(this.actions$.pipe(ofType(AuthActions.loadTeamsSuccess)),
          // no success event? no teams loaded, so go on
          filter(([loadTeamsAction, loadTeamsSuccessAction]) => !loadTeamsSuccessAction),
          // remove unnecessary action
          map(([loadTeams,]) => loadTeams),
          switchMap((action) =>
            this.apiService.teams$.pipe(
              tap(() => console.log('get teams request')),
              map((teams: Team[]) => AuthActions.loadTeamsSuccess({ teams })),
              catchError((error) => {
                console.log('err', error);
                return of(AuthActions.loadFailure({ error }));
              })
            )
          )
        );
      });