angularreduxredux-observableangular-router-guardsangular-redux

angular guard with angular-redux/store


I'm using @angular-redux/store in my project. I'm trying to create a guard with @select() decorator like this:

@select((s: IAppState) => s.user.userInformations.userState) userState$: Observable<number>;

and my canActivate method is like this :

canActivate(route, state: RouterStateSnapshot): Observable<boolean> {
    return this.userState$.pipe(map(value => {
      if (value === 0)
        return false;
      return true;
    }));
}

What is the problem? the userState$ always returns default value.(lets say undefined)

What I tried so far? I tried to filter Observable like this:

this.userState$.pipe(skipWhile(val => val === undefined)).subscribe(value => {
  console.log('value', value);
});

it works fine and return value is what I expected (in constructor). but I can't use this in canActivate method. I don't know what is the best way to map data in canActivate.

Briefly: I'm looking for a way to skip first value of state (the initial value) and use it in canActivate method as an Observable<boolean>.

P.S. it would be better if I could config @angular-redux/store to skip undefiend/initialed value in @Select() decorator by default.

Thanks for your helps.


Solution

  • I found the solution!

    We can use Promise to fix that. And since Promise doesn't return Observable, we should use from from rxjs. the final code is like this:

      @select((s: IAppState) => s.user.userInformations.userState) userState$: Observable<number>;
      userStatePromise = new Promise((resolve, reject) => {
        this.userState$.subscribe(val => {
          if (val !== undefined) {
            resolve(val)
          }
        }, (err) => {
          reject(err)
        })
      })
    
      canActivate(route, state: RouterStateSnapshot): Observable<boolean> {
    
        return from(this.userStatePromise).pipe(map(val => {
          if (val === 0) {
            // route anywhere you want
            return false;
          }
          return true;
        }))
    
      }