Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for ngrx state to be populated in async route guard

Tags:

angular

rxjs

ngrx

My route guard needs to wait for state to be populated, but I'm only ever getting the first value, which is of course, null

export class Guard implements CanActivate {

  constructor(
    private router: Router,
    private store: Store<AppState>,
  ) {}

  canActivate(): Observable<boolean> {
    return this.store.select<MyState>('mystate').map(state => {
      if (state && state.thing) {
        this.router.navigate(['/path']);
        return true;
      }
    });
  }

}

How can I force the guard to wait for the state to be populated?


[update 1]

If I employ the .skipWhile() pattern:

return this.store
           .select<MyState>('mystate')
           .skipWhile(mystate => {
             if (mystate && mystate.thing) {
               return false;
             }

             console.log('here');

             return true; // <- shouldn't this cause it to keep going?
           })
           .do(mystate => {
             if (mystate.thing.condition) {
               this.router.navigate(['/path']);
             }
           })
           .mapTo(true);

.do(...) is never evaluated, and 'here' is only logged once. What am I missing?


[update 2]

What was missing was the call to .dispatch() to load my state in the first place. I have a nested module structure, and the container component this guard was placed on was where .dispatch() lived. Of course, the guard, prevented the component from initializing, and therefore my state was never populated.

like image 648
Brandon Avatar asked Feb 25 '17 13:02

Brandon


1 Answers

You could use the skipWhile operator to skip the null value. That way the stream would only emit when the state is populated.

return this.store.select<MyState>('mystate')
  .skipWhile(state => !state || !state.thing)
  // at this point, you're guaranteed that `state` is populated
  .do(() => this.router.navigate(['/path']))
  .mapTo(true);

Here's a JSBIN: http://jsbin.com/lupicepoyo/1/edit?js,console

like image 111
AngularChef Avatar answered Sep 22 '22 01:09

AngularChef