FirebaseによるNext.jsの第一歩

[Firebase](
Firebase - Googlehttps://firebase.google.com › ...)は, フロントエンドの開発に専念できるように, バックエンドの処理をかなり簡単に実装することが可能なアプリケーションホスティングサービスです. 

今回はnext.jsでGoogle認証を紹介したいと思います. 

# Get started

## firebaseを扱う準備

```terminal
npm install firebase
```

プロジェクト直下に, 以下のようなファイルを用意します. ここで必要な変数は, [こちら](https://firebase.google.com/?hl=ja)からログインして発行してください. 

```.env.local
NEXT_PUBLIC_FIREBASE_API_KEY = *****
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN = *****
NEXT_PUBLIC_FIREBASE_PROJECT_ID= *****
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET = *****
NEXT_PUBLIC_FIREBASE_MESSEGING_SENDER_ID = *****
NEXT_PUBLIC_FIREBASE_APP_ID = *****
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID= *****

```

次に, srcディレクトリ内にファイルを作成していきます. 

## プロジェクト内にfirebaseを導入する

ここで定義される値を用いてデータのフェッチや, 認証情報の扱いを行います. 

```src/utils/firebase.js
import 'firebase/auth';
import { useRouter } from 'next/router';
import firebase from 'firebase/app';

const config = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSEGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

if (!firebase.apps.length) {
  firebase.initializeApp(config);
}

const Login = () => {
  const provider = new firebase.auth.GoogleAuthProvider();
  firebase
    .auth()
    .signInWithPopup(provider)
    .then(function (result) {
      router.push('/');
      return result;
    })
    .catch(function (error) {
      console.log(error);
      const errorCode = error.code;
      console.log(errorCode);
      const errorMessage = error.message;
      console.log(errorMessage);
    });
};

const Logout = async () => {await auth.signOut().then(() => {
  router.push('/')
}).catch((error) => {
  alert(error.message)
});}

const auth = firebase.auth();

export { firebase, auth, Login, Logout };
```

LoginやLogoutは, その名の通りの処理です. 
ボタンのonClick要素などにこれを適用することで, 任意の認証処理が実装できます. 詳しいことは[こちら](https://firebase.google.com/docs/auth/web/google-signin?hl=ja)がとてもわかりやすいです. 

## 認証情報をプロジェクト全体に適用
認証したはいいものの, このままではこの処理を全てのページで行うことになってしまいます. そこで用いるのが**useContext**です. 
詳しくは[こちら](https://panda-program.com/posts/react-usecontext-usereducer/#usereducer%E3%81%A0%E3%81%91%E3%82%92%E4%BD%BF%E3%81%86%E3%82%B1%E3%83%BC%E3%82%B9)を参照されていただきたいです. 

```src/auth/Auth.js
import { auth } from '../utils/firebase';
import { createContext, useEffect, useState } from 'react';

const AuthContext = createContext({ currentUser: undefined });

const AuthProvider = ({ children }) => {
    const [currentUser, setCurrentUser] = useState(undefined);

    useEffect(() => {
        auth.onAuthStateChanged((user) => {
          // ログイン状態が変化すると呼ばれる
          setCurrentUser(user);
        })
      }, []);
    return (
        <AuthContext.Provider value={{ currentUser: currentUser }}>
            {children}
        </AuthContext.Provider>
    );
}

export { AuthContext, AuthProvider }
```

## 任意のページに導入する

最後にボタンを設置して完成です. 

```src/pages/index.js
import React, { useContext  } from 'react';

import { AuthContext } from '../auth/Auth';
import {auth, Login, Logout } from '../utils/firebase';



export default function App() {

  const router = useRouter()
  const { currentUser } = useContext(AuthContext);


  return (
    <div>
      <main>
         <button onClick = {Login}>Login</button>
         <button onClick = {Logout}>Logout</button>
          {currentUser.displayName}

      </main>
      
    </div>
  )
}


```

ログインしているかどうかは, `currentUser`がnullか否かで判定できます. 


# ディレクトリ構成について

今回必要な最小要素について記載します. 

> project/
|┝ .next /
|┝ node_modules/
|┝ public/
|┝ src/
|　┝ auth/
|　　┝ Auth.js
|　┝ pages/
|　　┝ _app.js
|　　┝ index.js
|　┝ utils/
|　　┝ firebase.js
|┝ .env.local

以上です.