【问题标题】:AngularFire auth, template not updated when Observable<User> changesAngularFire 身份验证,Observable<User> 更改时模板未更新
【发布时间】:2020-02-02 15:29:37
【问题描述】:

我是 Angular 的临时用户,所以也许我遗漏了一些明显的东西。

我跟随 fireship.io 的 this lesson 使用 angularfire 在我的 Angular 应用程序中集成身份验证。

登录后,可观察的 AuthService.user$ 发生变化,但 UserProfile 组件中的模板没有更新。

使用下面的代码 sn-p 确认数据在那里。

<pre>{{auth.user$ | async | json}}</pre>

这似乎与在 ngzone 之外更新的 observable 有关。 我试图通过在组件中注入 ChangeDetectorRef 并从 AuthService.user$ 的订阅回调中触发 detectChange 来手动检测更改,但没有成功。

我只是通过将 user-profile.component.ts 更改为以下内容来使其按预期工作:

@Component({
  selector: 'app-user-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.css']
})
export class UserProfileComponent implements OnInit {

  userData?: User;

  constructor(public auth: AuthService) {
    this.auth.user$.subscribe(d => this.userData = d)
  }
}

并将user-profile.component.html改为如下:

<div *ngIf="userData; then authenticated else guest">
</div>

<ng-template #guest>
  <h3>Hello</h3>
  <p>Login to get started...</p>

  <button (click)="auth.googleLogin()">
    <i class="fa fa-google"></i> Connect Google
  </button>
</ng-template>

<ng-template #authenticated>
  <div *ngIf="userData as user">
    <h3>Hello, {{ user.displayName }}</h3>
    <img [src]="user.photoURL">
    <button (click)="auth.signOut()">Logout</button>
  </div>
</ng-template>

这是我的依赖项,从 package.json 中提取。

{
  "@angular/animations": "~8.2.14",
  "@angular/common": "~8.2.14",
  "@angular/compiler": "~8.2.14",
  "@angular/core": "~8.2.14",
  "@angular/fire": "^5.4.0",
  "@angular/forms": "~8.2.14",
  "@angular/platform-browser": "~8.2.14",
  "@angular/platform-browser-dynamic": "~8.2.14",
  "@angular/router": "~8.2.14",
  "firebase": "^7.8.0",
  "rxjs": "~6.4.0",
  "tslib": "^1.10.0",
  "zone.js": "~0.9.1"
}

知道我可能缺少什么吗?

【问题讨论】:

  • 你能在 stackblitz 上分享你的代码吗?
  • 它无法按原样运行,因为您需要在环境中提供有效的 firebase 配置。

标签: angular firebase google-cloud-platform angularfire


【解决方案1】:

除非我弄错了,否则您将稍微更改Jeff Delaney's example 的代码。

您在AuthService.user$ 上使用了两个ng-template 和两个async 订阅(一个在div 容器中,一个在ng-template 中称为authenticated。这就是原因你的问题。

使用下面的这段代码,它会顺利运行:

<div *ngIf="auth.user$ | async as user; else guest">
  <h3>Hello, {{ user.displayName }}</h3>
  <img [src]="user.photoURL">
  <button (click)="auth.signOut()">Logout</button>
</div>

<ng-template #guest>
   ...
</ng-template>

如果您想保留初始代码,可以考虑将 shareReplay 运算符添加到您的 AuthService.user$ observable。在这种情况下,Observable 的最后一个值将始终可用于新订阅。

this.user$ = this.afAuth.authState.pipe(
  switchMap(user => {
    if (user) {
      return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
    } else {
      return of(null);
    }
  }),
  shareReplay(1)
);

【讨论】:

  • 谢谢蒂埃里·法尔沃,您的回复很有帮助!虽然也许我错过了一些东西,但在我看来,Jeff Delaney 的代码有望在没有 shareReplay 运算符的情况下工作。也许它在最近发布的 Angular 中已经过时了?
  • 你是对的!但是您可以在 6:58 在video 中看到该代码与视频下方他的教程中的代码 sn-p 不同。一个div,只有一个ng-template,仅用于登录。 (没有新的 async 嵌套)。在这种情况下,您可以避免使用shareReplay 运算符。是的,您的代码正在运行,但 Jeff 在视频下方提到了依赖项(健康依赖项)。也许在他的教程上发布一个好问题?
猜你喜欢
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-09
  • 2017-11-11
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
相关资源
最近更新 更多