Search code examples
angularngrxngrx-effectstake

angular resolver with ngrx effect and take operator


i have a route in my app that uses a resolver to fetch data (array of objects) from the db. the resolve function check if the data exist in the store state (if the array has length), and if not it dispatches an effect to fetch the data from the db and wait for that effect to complete.

the fetch effect dispatches a "set" effect that can not through errors because it just set some values.

i want to fetch only once so in case the user refreshes the page he will still have the data he needed, but my code just keep trying to fetch because there is no data at first.

after i started to play a little with the code i got the following:

  1. if i will add the tap or the second switchMap (the one after the tap), i get an infinite loop
  2. if i delete the lines from "line number 1" (not including) till "line number 2" (including ), i don't get an infinite loop.

can anyone explain me this behavior?

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){ 
    return this.store.select('company').pipe(
      take(1),
      map(comState => {
        return comState.comps;
      }),
      switchMap(comps => {
       if(!comps.length){
        this.store.dispatch(new CompActions.FetchAll());
        return this.actions$.pipe( 
          ofType(CompActions.SET_ALL), 
          take(1), //------------ "line number 1"
          // tap(() => {
          //   this.router.navigate([state.url.split('/')[1]]);
          // }),
          switchMap(actionData => {
            const re = /\d+/;
            const compInd = re.exec(state.url);
            if(compInd && +compInd < actionData['payload']['length']){
              return of(actionData['payload']);
            }
            this.router.navigate([state.url.split('/')[1]]);
          })//------------ "line number 2"
        );
       } else {
         return of(comp); 
       }
      })
    )
  }

Solution

  • You should not navigate from inside a resolve block. If you do so, the guard is checked again and again. Angular will decide if you can navigate or not. The route you are going to navigate to is declared elsewhere.