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?
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?
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With