firebase.auth().currentUserとは
現在のユーザー認証情報を所持するプロパティです。
firebaseでは認証情報をクライアントに永続化が可能となっているので、永続化された認証情報が存在すれば
現在のユーザー認証情報
の対象となります。公式ドキュメント
リロードしようがブラウザ閉じようが認証状態は継続しているということですね、firebaseさまさまです。
本題
意気揚々Reactでこんなコードを書きます。
firebase.initializeApp({....})
const App = () => {
retutn <Router>
<LoginPage />
<HogePage />
<HugaPage />
<Router />
}
if (firebase.auth().currentUser !== null) {
console.log("前の認証情報が残っているよ!")
} else {
console.log("認証情報は残っていないよ!")
}
ReactDOM.render(<App />, document.getElementById("root"))
実行してみましょう、LoginPageで何かしら認証を行いリロード!
ですが表示されるのは
認証情報は残っていないよ!
無慈悲.....
調査するところ認証情報の永続化はデフォルトでsessionモードと言われるものとなっており、今回の意図通りの挙動をしてくれる様子です。公式ドキュメント
もう少し調べると、認証し→リロード→HogePageを動かしている際にはcurrentUserが参照できる
ここから推測するにcurrentUserにデータが入ってくるのはfirebaseSDKのモジュールが生成されるタイミングではないようで少しラグがあるようのでは。。。。。?
ですがcurrentUserに入ってくるタイミングなんてものはもちろん検知できません。
そこでAuth.onAuthStateChangedを発見、signin,signoutが発生した際にコールバックを処理してくれるようです。
使えそうなので書き換えてみましょう。
const getStoredFirebaseAuthenticatedUser = () =>
new Promise<firebase.User | null>(
(resolve, reject) => firebase.auth().onAuthStateChanged(resolve, reject)
);
firebase.initializeApp({....})
const App = () => {
return <Router>
<LoginPage />
<HogePage />
<HugaPage />
<Router />
}
getStoredFirebaseAuthenticatedUser().then(user => {
if (firebase.auth().currentUser !== null) {
console.log("前の認証情報が残っているよ!")
} else {
console.log("認証情報は残っていないよ!")
}
})
ReactDOM.render(<App />, document.getElementById("root"))
同じく、LoginPageで何かしら認証を行いリロードしてみます。
少し待ち
前の認証情報が残っているよ!
勝利!
まとめ
- 永続化された認証情報の参照でcurrentUserを使うとnullになるケースがある
- たぶんfirebaseSDKの初期化が終わってからcurrentUserに入るまでに時間がかかる
- 初期化終了の検知はできないからOnChangeAuthStateでフックしてあげようね
(ならcurrentUserの定義() => Promsie
にしろよ........)
ということでした、ハマったので皆さんお気をつけください。