AngularFire 身份验证,当 Observable<User> 更改时模板未更新
AngularFire auth, template not updated when Observable<User> changes
我是 Angular 的临时用户,所以我可能遗漏了一些明显的东西。
我跟随 fireship.io 的 this lesson 使用 angularfire 在我的 angular 应用程序中集成身份验证。
登录后,observable AuthService.user$ 发生变化,但 UserProfile 组件中的模板没有更新。
使用下面的代码片段确认数据在那里。
<pre>{{auth.user$ | async | json}}</pre>
这似乎与在 ngzone 之外更新的可观察对象有关。
我尝试通过在组件中注入 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"
}
知道我可能遗漏了什么吗?
除非我弄错了,否则您只是稍微更改了 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
的最后一个值将始终可用于新订阅。
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)
);
我是 Angular 的临时用户,所以我可能遗漏了一些明显的东西。
我跟随 fireship.io 的 this lesson 使用 angularfire 在我的 angular 应用程序中集成身份验证。
登录后,observable AuthService.user$ 发生变化,但 UserProfile 组件中的模板没有更新。
使用下面的代码片段确认数据在那里。
<pre>{{auth.user$ | async | json}}</pre>
这似乎与在 ngzone 之外更新的可观察对象有关。 我尝试通过在组件中注入 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"
}
知道我可能遗漏了什么吗?
除非我弄错了,否则您只是稍微更改了 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
的最后一个值将始终可用于新订阅。
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)
);