React + TypeScript + Firebase でユーザ登録_その2
はじめに
前回からの続きです。
今回は主にfirebaseの認証処理を書いていきます。
リポジトリ
サンプルのリポジトリはこちら。
github.com
Firebaseとの接続設定
お待たせしました。
いよいよFirebaseとの接続設定です。
まずはFirebaseの
『コンソール画面』→『Authentication』→右上にある『ウェブ設定』
をクリック。
すると、こんな画面が表示されるので
各値をメモなり覚えるなりしておきましょう。
次に、src/
配下にfirebase
というディレクトリを作り、それぞれのファイルを作成。
(実際にはディレクトリ名は何でもよい)
- auth.ts
- firebase.ts
firebase.ts
に設定を書き込み。
import * as firebase from "firebase/app"; import "firebase/auth"; const config = { apiKey: process.env.REACT_APP_FIREBASE_API_KEY, authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN, databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL, projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID, storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET, messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENSER_ID }; firebase.initializeApp(config); export default firebase;
以降のFirebase用の処理はfirebase.ts
でexportしたものを使用していきます。
ここで、process.env
という記述に注目。
これは環境変数から値を取得する為の記述です。
CRAでは、.env
というファイルを作成して、変数名の頭にREACT_APP_
と付けると
自動的に読んでくれるようになっています。
環境変数にapiKey等を設定したいので
プロジェクトrootに.env
ファイルを作成して、変数を定義しましょう。
REACT_APP_FIREBASE_API_KEY="your_apiKey" REACT_APP_FIREBASE_AUTH_DOMAIN="your_authDomain" REACT_APP_FIREBASE_DATABASE_URL="your_databaseURL" REACT_APP_FIREBASE_PROJECT_ID="your_projectId" REACT_APP_FIREBASE_STORAGE_BUCKET="your_storageBucket" REACT_APP_FIREBASE_MESSAGING_SENDER_ID="your_messagingSenderId"
先程ウェブ設定
画面で確認した値に対応する値を書いていきましょう。
ここまででアプリケーション側のfirebaseの接続設定が完了しました。
ユーザ登録処理
Firebaseへの登録処理
Firebaseへのユーザの登録処理を実装します。
auth.ts
に
import firebase from './firebase' // Sign Up export const signUp = (email: string, password: string) => { return firebase.auth().createUserWithEmailAndPassword(email, password) }
と書きます。
exportされたfirebase
をimportして、EmailとPasswordを引数に登録処理を行っています。
他にもGoogle認証やTwitter認証等行えますが、今回は割愛します。
認証ページの処理
先程書いた登録処理を画面側からコールできるようにします。
SignUp.tsxに処理を書いていきます。
// input要素が変更された時のハンドリング private handleChange = (event: any) => { + // エラー内容をクリア + this.setState({error: null}) + + if (event.target.name === "username") { + this.setState({username: event.target.value}); + } else if (event.target.name === "email") { + this.setState({email: event.target.value}); + } else if (event.target.name === "password") { + this.setState({password: event.target.value}); + } };
見たままですが、input要素内部が変更された時の処理です。
変更される度に呼ばれ、エラーが表示されていたらクリアし
その後state内容を更新している形です。
+ import {signUp} from "./firebase/auth"; ... // submitされた時の挙動 private handleSubmit = async (event: any) => { + event.preventDefault(); + // // Firebaseにサインアップ + try { + // emailとpasswordで登録 + const authUser = await signUp(this.state.data.email, this.state.data.password); + } catch (e) { + this.setState({ + error: e + }); + } };
こちらがFirebaseへのSignUp処理となります。
非同期処理で、importしたauth.ts
のsignUp
関数を読んでいます。
引数として渡すのは勿論state内のemailとpasswordです。
+ import TextField from "@material-ui/core/TextField/TextField"; ... // エラーハンドリング private handleError = () => { + let errorMessage = ""; + if (this.state.error.code === "auth/weak-password") { + errorMessage = "パスワードは6文字以上で入力して下さい。"; + } else { + errorMessage = this.state.error.message; + } + return ( + <TextField + error + fullWidth + id="filled-error" + label="Error" + value={errorMessage} + margin="normal" + variant="filled" + /> + ); };
こちらはエラーハンドリング処理です。
Firebaseからエラーが返ってきた場合にstate内のerrorにオブジェクトが入るので
その中のcodeを判定してエラーメッセージを設定しています。
現状はweak-passwordのみ、自分で定義したエラーメッセージを表示しています。
(他のエラーメッセージはそのまま出ちゃいます)
SignUp
ここまででSignUp処理の完成です。
npm start
して実際に登録してみましょう。
正しく登録されているか確認する場合は
Firebaseコンソール
→Authentication
→ユーザ
タブに進んで見てみましょう。
正しく登録されています。
FireStoreを使ったユーザ情報の登録
ここまででユーザ自体の登録はできましたが
肝心のユーザ情報(ここではユーザ名)が登録できていません。
そこで、FireStore
を使ってユーザ情報を登録してみましょう。
まずはFirebaseコンソール
→Database
に進み
データベースの作成
ボタンを押下。
今回はテストなのでテストモードで開始
にチェックを入れて有効にします。
しばらく待つと、管理画面に移行します。
コレクションを追加
を押下します。
今回はusers
という名前でコレクションを作成します。
次に、最初のドキュメントを追加します。
なんでもいいのですが、ドキュメントIDは空、
フィールドは以下で作りました。
- username: string, 'root'
- email: string, 'root@hoge.com'
これでFireStoreが使えるようになりました。
次に、src/firebase
配下にdb.ts
ファイルを作成。
以下の記述を行います。
import firebase from "./firebase"; import 'firebase/firestore'; /* ユーザ情報 */ interface User { uid: string, name: string, email: string } /* ユーザ情報の更新 */ export const updateUser = (user: User) => { firebase.firestore().collection('users').doc(user.uid).set({ username: user.name, email: user.email }); };
これも見ての通りですが、importしたfirebase
の
firestore().collection('users')
でFireStoreのusers
コレクションを指定し
ドキュメントのキーとして、SignUp時に作成したユーザのuid
を設定しています。
そして中身のフィールドに、受け取ったemailとusernameを設定しています。
大体直観的に使えるのではないでしょうか。
後はSignUp時に同時にユーザ情報を登録するだけですね。
SignUpページのSignUp関数に以下追記を行いましょう。
... const authUser = await signUp(this.state.email, this.state.password); + // ユーザ情報の更新 + if (authUser.user) { + await updateUser({uid: authUser.user.uid, name: this.state.username, email: this.state.email}); + } } catch (e) { ...
さっきと同じように、認証ページに飛んで登録してみます。
Authenticationで登録したユーザのuidと同じドキュメントで
入力したフィールドが保存されていたら成功です!
お疲れ様でした。
まとめ
中々長くなってしまいました。
ですが簡単な登録処理だったらこんな感じかなと思います。
本当はここに
- ログイン処理
- 登録後の自動ログイン
- ログイン状態を判定してリダイレクト
- 登録時のValidate処理
- ...etc
なんかも追加したかったのですが、本来の意図(とりあえずの実装)
から外れそうだったので割愛しました。
余力があればそのあたりも実装してアップデートしたいです。
それでは最後に参考文献を。
参考文献
qiita.com material-ui.com github.com qiita.com firebase.google.com masamichi.me
現場からは以上です。