[英]How to use NgRx Store in a Router Guard?
有人問過類似的問題,但沒有一個解決方案對我有用。 我店的state是:
export interface AuthState {
isLoggedIn: boolean,
...
}
我想在路由器防護中使用isLoggedIn
,所以我有這樣的東西:
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router,
private store: Store<fromAuth.AuthState>) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.canNavigate();
}
canNavigate(): Observable<boolean> {
return this.store.select(AuthSelectors.selectIsLoggedIn).pipe(
filter(isLoggedin => isLoggedin), // issue comes from here
tap(isLoggedId => {
if (!isLoggedId) {
this.router.navigateByUrl('/login').then()
}
})
);
}
}
這段代碼在用戶剛剛登錄時運行良好,但在我們重新加載應用程序且本地沒有令牌時無法運行。 重新加載應用程序后,我有一個空白頁面,因為filter()
方法被卡住了。
我實現了一個autoLogin()
方法,該方法在我們重新加載應用程序時分派一個操作以將商店中的isLoggedIn
設置為 true,它可以工作,但在沒有令牌時會出現同樣的問題。 問題是當isLoggedIn
為 false 時如何繞過filter()
並重定向到登錄頁面?
編輯
這是autoLogin()
方法的代碼:
autoLogin() {
from(getTokenFromLocalStorage()).pipe(
tap(token => {
if (token) {
this.store.dispatch(AuthActions.autoLogin({payload: token}));
}
})
).subscribe();
}
然后在reducer
中更新isLoggedIn
字段。 autoLogin()
:
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent implements OnInit {
constructor(private authenticationService: AuthenticationService) {}
ngOnInit() {
console.log("App start");
this.authenticationService.autoLogin();
}
}
@brunoj 的回答建議刪除filter()
function,我不能這樣做,因為AuthGuard#canActivate()
方法在 reducer 之前執行,所以在更新isLoggedIn
字段之前執行。 filter()
允許等待 reducer 中的更新。
就像 DeborahK 所說的過濾運算符過濾每個 isLoggedin 虛假值。 您只需要從 stream 中刪除過濾器運算符。當您的 stream 具有錯誤值時,導航將被取消,您的點擊運算符將被執行,用戶將被重定向到登錄頁面。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.