I have a user service which allows login, logout and maintains data about the currently logged in user:
user$ = this.http.get<User>('/api/user')
.pipe(
shareReplay(1),
);
I am using shareReplay(1)
because I do not want the webservice to be called several times.
On one of the components, I have this (for simplicity), but I have several other things I want to do if a user is logged in:
<div *ngIf="isUserLoggedIn$ | async">Logout</div>
isUserLoggedIn$ = this.userService.user$
.pipe(
map(user => user != null),
catchError(error => of(false)),
);
However, the isLoggedIn$
does not change after the user logs in or logs out. It does change when I refresh the page.
Here's my logout code:
logout() {
console.log('logging out');
this.cookieService.deleteAll('/');
this.user$ = null;
console.log('redirecting');
this.router.navigateByUrl('/login');
}
I understand that the internal observable is not reset if I assign the variable to null.
So, for logout, I took clue from this answer: https://stackoverflow.com/a/56031703 about refreshing a shareReplay()
. But, the user$ being used in the templates causes my application to go into a tizzy as soon as I attempt to logout.
In one of my attempts, I tried BehaviorSubject
:
user$ = new BehaviorSubject<User>(null);
constructor() {
this.http.get<User>('/api/user')
.pipe(take(1), map((user) => this.user$.next(user))
.subscribe();
}
logout() {
...
this.user$.next(null);
...
}
This works a little better except when I refresh the page. The auth-guard (CanActivate
) always gets the user$ as null and redirects to the login page.
This seemed like an easy thing to do when I started out, but I am going on falling into a deeper hole with each change. Is there a solution to this?