前提・実現したいこと
新規ユーザー登録をした直後に、ユーザーネームを画面に表示したい。
発生している問題
サインインで登録した直後にfirebaseのデータベース(Firestore)を見ると
・usersコレクションの中にuidがあり
・Authenticationにアカウントが登録されている
サインインで登録した直後ではemailとuidしか存在していなくて、displayNameはnullです。
しかし一度リロードすると、サインイン時に入力した名前がdisplayNameが登録されます。
該当のソースコード
auth.service.ts
typescript
1import { Injectable } from '@angular/core'; 2import { Router } from '@angular/router'; 3import { AngularFireAuth } from '@angular/fire/auth'; 4import { Observable } from 'rxjs'; 5import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore'; 6import { switchMap } from 'rxjs/operators'; 7 8export interface User { 9 uid: string; 10 email: string; 11 displayName?: string; 12 myCustomData?: string; 13 photoURL?: string; 14} 15 16@Injectable({ 17 providedIn: 'root' 18}) 19 20export class AuthService { 21 user$: Observable<User[]>; 22 23 24 constructor( 25 private router: Router, 26 private afs: AngularFirestore, 27 private afAuth: AngularFireAuth 28 ) { 29 this.user$ = this.afAuth.authState.pipe( 30 switchMap(user => { 31 if (user) { 32 this.updateUserData(user); 33 console.log('auth.service ' + user.displayName); 34 return this.afs.doc<User[]>(`users/${user.uid}`).valueChanges(); 35 } else { 36 this.router.navigateByUrl('/auth'); 37 } 38 }) 39 ); 40 } 41 42 async login(email: string, password: string) { 43 await this.afAuth.auth.signInWithEmailAndPassword(email, password) 44 .then((user) => { 45 console.log(user); 46 this.router.navigateByUrl('/'); 47 }) 48 .catch((error) => { 49 console.log(error); 50 this.router.navigateByUrl('/auth'); 51 }); 52 } 53 54 async logout() { 55 await this.afAuth.auth.signOut(); 56 this.router.navigateByUrl('/auth'); 57 } 58 59 updateUserData(user) { 60 // ログイン時にユーザーデータをfirestoreに設定 61 const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`); 62 const data = { 63 uid: user.uid, 64 email: user.email, 65 displayName: user.displayName, 66 photoURL: user.photoURL 67 }; 68 console.log(data); 69 return userRef.set(data, { merge: true }); 70 } 71}
signup.page.ts
typescript
1import { Router } from '@angular/router'; 2import { AuthService } from './../auth/auth.service'; 3import { Component, OnInit } from '@angular/core'; 4import { AngularFireAuth } from '@angular/fire/auth'; 5import { ToastController } from '@ionic/angular'; 6 7@Component({ 8 selector: 'app-signup', 9 templateUrl: './signup.page.html', 10 styleUrls: ['./signup.page.scss'], 11}) 12export class SignupPage implements OnInit { 13 signup: { 14 email: string; 15 password: string; 16 name: string; 17 } = { 18 email: '', 19 password: '', 20 name: '', 21 }; 22 23 24 constructor( 25 private router: Router, 26 private afAuth: AngularFireAuth, 27 private toastCtrl: ToastController, 28 private authService: AuthService 29 ) { } 30 31 ngOnInit() { 32 } 33 34 signUp() { 35 this.afAuth.auth 36 .createUserWithEmailAndPassword(this.signup.email, this.signup.password) 37 .then((created) => { 38 const newUser = created.user; 39 newUser.updateProfile({ 40 displayName: this.signup.name, 41 photoURL: '' 42 }) 43 .catch((error) => { 44 console.log('signUpでエラー: ' + error); 45 this.router.navigateByUrl('/signup'); 46 }) 47 .then(async () => { 48 const toast = await this.toastCtrl.create({ 49 // 入力した名前が表示される 50 message: `${created.user.displayName}さんを登録しました`, 51 duration: 3000 52 }); 53 await toast.present(); 54 this.authService.updateUserData(newUser); 55 }) 56 .catch(async error => { 57 const toast = await this.toastCtrl.create({ 58 message: error.toString(), 59 duration: 3000 60 }); 61 await toast.present(); 62 }); 63 this.router.navigateByUrl('/'); 64 }); 65 } 66 67 goLogin() { 68 this.router.navigateByUrl('/auth'); 69 } 70}
home.page.ts
html
1<ion-header> 2 <ion-toolbar> 3 <ion-title>リスト</ion-title> 4 <ion-buttons slot="end"> 5 <ion-button (click)="logout()"> 6 ログアウト 7 </ion-button> 8 </ion-buttons> 9 </ion-toolbar> 10</ion-header> 11 12<ion-content> 13 <div *ngIf="authService.user$ | async as user"> 14 <!-- user.displayNameは一度リロードした後なら表示される --> 15 <h3>Howdy, {{ user.displayName }}</h3> 16 <p>UID: {{ user.uid }}</p> 17 </div> 18</ion-content> 19
##エラー
「ユーザー登録でdisplayNameがnullになる」とは関係ないかもですが、、、。
ログアウトした時に毎回発生します。コンソールにエラーは出るが、今の所特に問題なく動く。
Uncaught TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. at subscribeTo (subscribeTo.js:27) at subscribeToResult (subscribeToResult.js:11) at SwitchMapSubscriber._innerSub (switchMap.js:46) at SwitchMapSubscriber._next (switchMap.js:36) at SwitchMapSubscriber.next (Subscriber.js:49) at angularfire2.js:44 at ZoneDelegate.invoke (zone-evergreen.js:359) at Object.onInvoke (core.js:34201) at ZoneDelegate.invoke (zone-evergreen.js:358) at Zone.run (zone-evergreen.js:124)
補足情報(FW/ツールのバージョンなど)
ionic info
Ionic: Ionic CLI : 5.2.8 (/usr/local/lib/node_modules/ionic) Ionic Framework : @ionic/angular 4.8.0 @angular-devkit/build-angular : 0.801.3 @angular-devkit/schematics : 8.1.3 @angular/cli : 8.1.3 @ionic/angular-toolkit : 2.0.0 Utility: cordova-res : 0.6.0 native-run : 0.2.8 System: NodeJS : v10.15.1 (/usr/local/bin/node) npm : 6.4.1 OS : macOS Mojave
##参考にしたサイト
https://fireship.io/lessons/angularfire-google-oauth/
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。