メールアドレスのフォーマットはチェックできてもメールアドレスが本当に存在しているのかは実際にメールを送らないとわかりません。Firebaseではメールを送る事でメールアドレスを有効化する事ができます。
React Firebase入門シリーズ
1-1・ React Firebase入門 初期設定とsignup - masalibの日記
1-2・ 「react-hook-form」を入れてみた - masalibの日記
1-3・ React Firebase入門 signupの通信エラー対応 - masalibの日記
2・ React Firebase入門 ログイン処理 - masalibの日記
3・ React Firebase入門 ログイン認証とログアウト処理 - masalibの日記
4・ React Firebase入門 パスワード初期化処理 - masalibの日記
5・React Firebase入門 メールアドレスの有効化 今ここ
メールアドレスの有効化とは
- userに認証URLがついたメールを送付
- userが認証URLにアクセス
この2つで有効化にできます
メールのテンプレートの変更
パスワード初期化と同様にメールのテンプレートはFirebase側が用意してくれています。ただデフォルト設定は英語なので日本語にします
メールアドレス処理
contextに処理をつくってその関数を共有させるだけです。
ソース
全文はたぶん見なくても大丈夫かと思う。
クリックすると展開されます(長文なので注意)
import React, { useContext, useState, useEffect } from "react" import { auth } from "../firebase" const AuthContext = React.createContext() export function useAuth() { return useContext(AuthContext) } export function AuthProvider({ children }) { const [currentUser, setCurrentUser] = useState() const [loading, setLoading] = useState(true) function signup(email, password) { return auth.createUserWithEmailAndPassword(email, password) } function login(email, password) { return auth.signInWithEmailAndPassword(email, password) } function logout() { return auth.signOut() } function sendEmailVerification(){ const actionCodeSettings = { url: 'http://localhost:3000/dashboard' , } return currentUser.sendEmailVerification(actionCodeSettings) } function resetPassword(email) { //https://firebase.google.com/docs/auth/web/passing-state-in-email-actions const actionCodeSettings = { url: 'http://localhost:3000/?email=' + email, /* iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, handleCodeInApp: true, // When multiple custom dynamic link domains are defined, specify which // one to use. dynamicLinkDomain: "example.page.link" */ }; return auth.sendPasswordResetEmail(email,actionCodeSettings) } const value = { currentUser, signup, login, logout, resetPassword, sendEmailVerification } useEffect(() => { // Firebase Authのメソッド。ログイン状態が変化すると呼び出される auth.onAuthStateChanged(user => { setCurrentUser(user); setLoading(false) }); }, []); return ( <AuthContext.Provider value={value}> {!loading && children} </AuthContext.Provider> ) }
ソースの解説
追加したのはsendEmailVerificationという関数です。
function sendEmailVerification(){ const actionCodeSettings = { url: 'http://localhost:3000/dashboard' , } return currentUser.sendEmailVerification(actionCodeSettings) }
actionCodeSettingsについては前回の
React Firebase入門 パスワード初期化処理 - masalibの日記
を参照してください
共通するためのvalueの値を修正
const value = {
currentUser,
signup,
login,
logout,
resetPassword,
+ sendEmailVerification
}
ダッシュボードにボタンを追加
最終的にはユーザーのプロフィールの画面などで有効化のボタンを配置したいのですが、手っ取り早くダッシュボードに設置しました
画面のソース
クリックすると展開されます(長文なので注意)
import React, { useState } from 'react' import { useAuth } from "../contexts/AuthContext" import { Link, useHistory } from "react-router-dom" import Button from "@material-ui/core/Button"; import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; const useStyles = makeStyles((theme: Theme) => createStyles({ container: { display: "flex", flexWrap: "wrap", width: 400, margin: `${theme.spacing(0)} auto` }, logoutBtn: { margin: theme.spacing(2), flexGrow: 1 }, handlesendEmailVerificationBtn: { margin: theme.spacing(2), flexGrow: 1 }, header: { textAlign: "center", background: "#212121", color: "#fff" }, card: { marginTop: theme.spacing(10) } }) ); const Dashboard = () => { const classes = useStyles(); const [error, setError] = useState("") const { currentUser, logout ,sendEmailVerification} = useAuth() const history = useHistory() async function handleLogout() { setError("") try { await logout() history.push("/") } catch { setError("Failed to log out") } } async function handlesendEmailVerification() { setError("") //setError("メールをおくりました。メール有効化をお願いします") try { await sendEmailVerification() setError("メールをおくりました。メール有効化をお願いします") } catch (e){ console.log(e) setError("有効化メールの送信に失敗しました") } } return ( <div> Dashboard テスト用のリンク(あとで治す) {error && <div style={{ color: "red" }}>{error}</div>} <strong>Email:</strong> {currentUser.email} <h2> <Link to="/login">Login</Link> </h2> <h2> <Link to="/signup">signup</Link> </h2> <div> <Button variant="contained" size="large" color="secondary" className={classes.logoutBtn} onClick={handleLogout} > Logout </Button> </div> <div> <Button variant="contained" size="large" color="secondary" className={classes.handlesendEmailVerificationBtn} onClick={handlesendEmailVerification} > handlesendEmailVerification </Button> </div> </div> ) } export default Dashboard
画面のソース解説
async function handlesendEmailVerification() { setError("") try { await sendEmailVerification() setError("メールをおくりました。メール有効化をお願いします") } catch (e){ console.log(e) setError("有効化メールの送信に失敗しました") } }
作った try-catchで関数を読んでいるだけです。成功した場合に画面にメッセージを表示させています。バリデーションもいらないので比較的簡単です
結果
- handlesendEmailVerificationのボタンを押す
- メールが届く
- URLにアクセスして完了画面が表示される
- サイトのトップに戻ってくる
画面には出していないのですが、currentUserの内容を確認すると
emailVerifiedという設定値が変わっていることが確認できます
感想
- 完了画面メッセージは変えれないみたい・・・これだとメールアドレスが認証されていない場合のページを用意しないとおかしい。なんてこった