以下の React で作ったアプリに Firebase Authentication を導入してみようと思う
Glossary
今回実装したコードはこちら
GitHub - kurosame/glossary: Glossary App using React
Firebase 側の設定
Firebase の Authentication からログイン方法を設定をクリック
Google 認証を有効にして保存
Firebase の初期設定
npm i firebase
Firebase のサービスを使う際は以下の設定が必要
下記の情報は Firebase からコピペできる
ちなみに隠してるけど、これらの情報は公開してもセキュアです
// firebase/config.ts const config = { apiKey: '...', authDomain: '...', databaseURL: '...', projectId: '...', storageBucket: '...', messagingSenderId: '...' } export default config
Firebase を初期設定する
// firebase/index.ts import firebase from 'firebase/app' import 'firebase/auth' import config from '@/firebase/config' const firebaseApp = firebase.initializeApp(config) export const auth = firebaseApp.auth()
ログイン画面を実装
ログインフローは全て FirebaseUI に任せる
FirebaseUI の React ラッパーが公式であるので、こちらを使って実装する
npm i react-firebaseui
以下は FirebaseUI の Config 設定
ログインの表示方法や認証後の遷移先、認証の種類を定義する
// firebase/ui-config.ts import firebase from 'firebase/app' import 'firebase/auth' const uiConfig = { signInFlow: 'popup', signInSuccessUrl: '/', signInOptions: [firebase.auth.GoogleAuthProvider.PROVIDER_ID] } export default uiConfig
以下はログイン画面
Redux 周りの説明は省略します
componentDidMount ライフサイクル関数で Firebase の onAuthStateChanged オブサーバー関数を使って、user を取得している
user が取れればログイン済と判断し、null の場合は未ログインと判断している
そして、render 関数内で Store に保持している isLogin を使って、レンダリング有無を判断している
今回 isLogin を他のコンポーネントで使うため、Redux を使って Store に保持したが、他で使う用途が無ければ Local State で良い
また、firebase.auth().currentUser
を使っても同様にログイン有無の判断ができるが、タイミングによってはログイン後でも null を返す場合がある
firebase.auth()
が初期化されてないタイミングで currentUser を呼び出すと null になるらしい
推奨されている解決方法は onAuthStateChanged 関数のコールバックで user を受け取り、処理を行うことです
currentUser を使うのは、onAuthStateChanged 関数の処理の後が良いと思う
// Login.tsx import React from 'react' import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth' import { connect } from 'react-redux' import { bindActionCreators, Dispatch } from 'redux' import uiConfig from '@/firebase/ui-config' import { auth } from '@/firebase/index' import { States } from '@/modules/states' import { LoginActions, LoginState, setIsLogin } from '@/modules/login' interface Props { state: { login: LoginState } actions: LoginActions } export class Login extends React.PureComponent<Props> { componentDidMount(): void { auth.onAuthStateChanged(user => this.props.actions.setIsLogin({ isLogin: !!user }) ) // ログイン済であればnull、未ログインであればStyledFirebaseAuthを返す public render(): JSX.Element | null { if (this.props.state.login.isLogin) return null return <StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={auth} /> } } export default connect( (states: States) => ({ state: { login: states.login } }), (dispatch: Dispatch) => ({ actions: { setIsLogin: bindActionCreators(setIsLogin, dispatch) } }) )(Login)
動作確認
アプリを実行すると、以下のよく見る Google ログインが表示されるので、Google アカウントを使ってログインする
ログイン後、Firebase コンソールのプロジェクトで Authentication タブを確認すると、ログインしたユーザが表示されていると思う
また、onAuthStateChanged 関数を使って、Store に保存した isLogin を見ると、ログイン済は true、未ログインは false が設定されていると思う