本記事ではReact(TypeScript)アプリにFirebaseを使った認証機能を組み込む方法を紹介します。認証はメールアドレスとパスワードを使った認証とGoogleアカウントを使った認証の2種類で行えるようにしています。見栄えは多少よくしてレスポンシブ対応も軽く行っています。なおコンポーネント間のユーザー情報の共有は、Reduxは使わずContextとHooksで行っています。
ソースコードはGitHubで公開していますので、よかったらご利用ください。
React/TypeScriptによるFirebase認証アプリ. Contribute to ganeo/react-…
完成イメージ
トップページ(パス: /)では2種類のログイン(メールアドレス/パスワードおよびGoogle)とメールアドレス/パスワード認証用のサインアップができます。ログインするとホームページ(パス: /home)に遷移します(ログイン済みだとトップページを開こうとしてもホームページにとびます)。ホームページはログインしていないと入れません。
Firebase側の設定
プロジェクトの作成
Firebaseにログインしてプロジェクトを作成します。プロジェクト名は後ほど作成するReactのアプリ名と揃えて「react-firebase-auth-sample」としておきます。Googleアナリティクスは無効にしてさくっとプロジェクトを作成します。
認証機能の有効化
作成したプロジェクトの「Authentication」メニューから「Sign-in method」タブを選択して「メール/パスワード」と「Google」の認証を有効にします。
Webアプリの追加
プロジェクトのホーム画面で「</>」ボタンをクリックしてWebアプリを追加します。アプリを追加するとFirebaseに接続するためのAPIキーなどを取得できます。この情報は次に作成するReactアプリで利用します。
React/TypeScriptの実装
React/TypeScriptアプリの雛形を作成
TypeScript用Reactアプリをcreate react appコマンドで作成します。
利用するパッケージのインストール
FirebaseのSDKとルーティング用のパッケージをインストールします。上記で作成したReactアプリのルートディレクトリで次のコマンドを実行します。
ソースコードの編集
以下では認証に関わる部分だけを抜粋して説明しています。ちなみに追加したCSSはデフォルトで存在するApp.cssを上書きして全てここに記述しています。
Firebase接続用キーを環境変数として設定
Firebase接続用キーをソースコードに直接書くのは流出の危険性が増すので、Reactの雛形アプリに標準で備わっている環境変数読み込み機能を使います。
Reactアプリのルートディレクトリに「.env」ファイルを作成して接頭辞「REACT_APP」の変数にFirebase側の作業で取得したAPIキーなどをセットします(ダブルクォーテーションは不要です)。「.env」は.gitignoreに設定しておきます。これだけで「process.env.<環境変数名>」として簡単に環境変数を参照することができます。
REACT_APP_FIREBASE_KEY=<apiKey>
REACT_APP_FIREBASE_DOMAIN=<authDomain>
REACT_APP_FIREBASE_DATABASE=<databaseURL>
REACT_APP_FIREBASE_PROJECT_ID=<projectId>
REACT_APP_FIREBASE_STORAGE_BUCKET=<storageBucket>
REACT_APP_FIREBASE_SENDER_ID=<messagingSenderId>
Firebase用機能を集約したコンポーネントを作成
Firebaseのための関数群はfirebase.tsxという1ファイルを作成してここに集約します。
下記赤字部分でFirebase接続用のキーを環境変数から参照してFirebase用インスタンスを取得しています。
青字部分で上から順にメール/パスワード認証のログイン、Google認証のログイン、メール/パスワード認証のサインアップ、ログアウト用の関数を定義しています。
緑字部分の主な処理はFirebaseに認証ユーザーを問い合せた後にユーザー情報をStateにセットしています。そしてContextを使って子コンポーネントにそのユーザー情報を渡せるようにしています。
// firebase.tsx import React, { useEffect, useState } from 'react' import firebase from 'firebase/app' import 'firebase/auth' import { FirebaseContext } from './contexts' export const app = firebase.initializeApp({ apiKey: process.env.REACT_APP_FIREBASE_KEY, authDomain: process.env.REACT_APP_FIREBASE_DOMAIN, databaseURL: process.env.REACT_APP_FIREBASE_DATABASE, projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID, storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET, messagingSenderId: process.env.REACT_APP_FIREBASE_SENDER_ID, }) export const loginWithEmail = async (email: string, password: string) => { try { await app.auth().signInWithEmailAndPassword(email, password) } catch (error) { alert(error) } } export const loginWithGoogle = async () => { const provider = new firebase.auth.GoogleAuthProvider() try { await firebase.auth().signInWithPopup(provider) } catch (error) { alert(error) } } export const signupWithEmail = async (email: string, password: string) => { try { await app.auth().createUserWithEmailAndPassword(email, password) } catch (error) { alert(error) } } export const logout = () => { app.auth().signOut() } export const FirebaseProvider: React.FC = ({ children }) => { const [user, setUser] = useState(null) const [pending, setPending] = useState(true) useEffect(() => { app.auth().onAuthStateChanged((user) => { setUser(user) setPending(false) }) }, []) if (pending) { return <div className='loading'>ローディング中...</div> } return ( <FirebaseContext.Provider value={{ user, }} > {children} </FirebaseContext.Provider'> ) }
子コンポーネント(Home)では下記緑字のとおりContextからユーザー情報を取得して利用しています。
// Home.tsx import React, { useContext } from 'react' import { logout } from '../firebase' import { FirebaseContext } from '../contexts' const Home = () => { const { user } = useContext(FirebaseContext) return ( <> <header className='header-page'> <h1>Home(要ログイン)</h1> </header> <div className='wrap-home'> <p>{user?.email}でログインしています。</p> <button onClick={logout}>ログアウト</button> </div> </> ) } export default Home
後続記事
前回の記事(以下にリンク添付)ではFirebaseのAuthenticationを使って認証アプリを作成しましたが、本記事ではログインすると表示されるページにメモを追加/表示/更新/削除できる機能を実装します。データの保存にはFirebas[…]
参考
React Router公式ドキュメント(認証サンプル)
Firebase公式ドキュメント(Authentication)