在整个应用程序中存储登录状态以驱动 UI 组件

问题描述 投票:0回答:1

我正在尝试在我的角度应用程序中创建一个基本的登录/注销系统,其基本功能如下:

  • 如果用户已通过身份验证,则隐藏/显示登录/注销按钮。

我有一个连接到 mongodb 数据库的 fastify 服务器,工作正常,我可以登录并且 JWT 返回到前端。当用户登录或注销时,我无法更新 UI。为了简单起见(一旦我弄清楚这个问题,我将重构),我纯粹根据令牌是否存在来驱动 UI 更改。

授权/用户服务:

@Injectable({
  providedIn: 'root',
})
export class UserService {
  router = inject(Router);
  http = inject(HttpClient);

  private tokenSubject = new BehaviorSubject<string | null>(null);
  public token: Observable<string | null> = this.tokenSubject.asObservable();

  constructor() {
    const storedToken = localStorage.getItem('token');
    if (storedToken) {
      this.tokenSubject.next(storedToken);
    }
  }

  public get tokenValue(): string | null {
    return this.tokenSubject.value;
  }

  login(login: Login): Observable<UserToken> {
    return this.http.post<UserToken>(`${environment.apiUrl}/login`, login).pipe(
      map((token) => {
        console.log('token', token);
        localStorage.setItem('token', token.token);
        this.router.navigate(['/test']);
        return token;
      })
    );
  }

  logout(): void {
    localStorage.removeItem('token');
    this.tokenSubject.next(null);

    this.router.navigate(['/login']);
  }

  register(user: SignUp): Observable<string> {
    return this.http.post<string>(`${environment.apiUrl}/register`, user);
  }
}

登录并返回令牌后,我想隐藏导航组件中使用的登录按钮:

<div class="navbar bg-base-100">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl" routerLink="/">Kilvey League</a>
  </div>
  <div class="flex-none">
    <ul class="menu menu-horizontal px-1">
      @if(!(isLoggedIn$ | async) ){
      <li routerLink="/signup" routerLinkActive="['active']">
        <a>Sign Up</a>
      </li>
      <li routerLink="/login"><a>Login</a></li>
      } @else {
      <li routerLink="/create-match"><a>Create Match</a></li>
      <li (click)="logout()"><a>Logout</a></li>
      }
    </ul>
  </div>
</div>

export class NavigationComponent {
  userService = inject(UserService);
  isLoggedIn$ = this.userService.token;

  async logout() {
    await this.userService.logout();
  }
}

这使用来自用户服务的令牌,但在登录并路由到

/create-match
后,登录按钮仍然存在。如果我刷新,登录会更改为注销,但我希望它实时更改。

angular rxjs
1个回答
0
投票

根据您共享的代码,我认为从

token
观察到的
UserService
在成功登录后并未更新。

更新它会通过

token
可观察到的发出一个新值,并且注册/登录按钮应该隐藏

  login(login: Login): Observable<UserToken> {
    return this.http.post<UserToken>(`${environment.apiUrl}/login`, login).pipe(
      map((token) => {
        console.log('token', token);
        localStorage.setItem('token', token.token);
        this.tokenSubject.next(token); // <- update token observable
        this.router.navigate(['/test']);
        return token;
      })
    );
  }
© www.soinside.com 2019 - 2024. All rights reserved.