Firebase Authのログイン状態をReact Contextで扱う実装ステップまとめ💖

みなさま！！ごきげんよう💖

🗣️「Firebaseでログイン機能をつけたのに、ユーザー情報がうまく使い回せない…」
🗣️「ログインしてるのに表示が変わらない…なんで？？」

そんな壁にぶつかっていませんか？

ReactアプリでFirebase Authを使ってログイン機能を実装するだけなら意外と簡単なのよ🧚‍♂️
でも、“ログイン状態をアプリ全体で使えるように管理する”には、ContextやProviderといった少し抽象的な仕組みを理解する必要がありますの。

この記事では、そんな **「ログイン状態の全体管理」** をReactとFirebaseを使って、
初学者でもイメージしやすいステップで実装できるようにわかりやすく解説していきますのよ💡✨




### 🌟この記事でわかること
・Firebase Authでのログイン状態管理の全体像

・Context × Provider × useContext の関係

・実装中につまづきやすいポイントとその解決法⭐️

### 💡 ざっくり全体の流れ
アプリを作っていて「ユーザーがログインしているかどうか、どこでも知りたい！」って思うこと、ありますわよね？

たとえば…

🗣️ヘッダーで「こんにちは、○○さん」って表示したいとき

🗣️プロフィール画面でアイコンや名前を表示したいとき

こういうときに使うのが **「Context」と「Provider」** という仕組みなのですの✨


### ✅ 登場人物の役割まとめ

| 名前             | 役割                                         |
| -------------- | ------------------------------------------ |
| Context      | ユーザー情報を保存しておく“共有スペース”みたいなもの！             |
| Provider    | そのスペースにFirebaseから取得したユーザー情報を入れるお仕事をしてくれますの🧚‍♂️ |
| useContext() | 情報が必要な場所で、情報を取り出すために使いますのよ！！                 |

>今から説明を始めるけど、、、妄想しながら読んでね🧚‍♂️
>ただ読んでいると頭がたくさんになってしまうから！！ね！！

### 全体の流れまとめ（ログイン〜表示まで）

① signInWithPopup でログイン処理を実行 🖱
　↓
② Firebase Auth がログイン状態（トークン）をブラウザに自動保存 🔐
　↓
③ アプリ起動時に onAuthStateChanged が発火し、ログイン状態を検知 📣
　↓
④ FirebaseUserProvider の中で setUser() により user を useState に保存 📦
　↓
⑤ その user を Context.Provider に渡して、アプリ全体に共有 🎁
　↓
⑥ 任意の子コンポーネントで useContext() を使って user を取得 ✨

>🔍 onAuthStateChanged は、アプリが起動したときに Firebase がユーザーのログイン状態を検知して、自動で呼び出してくれる関数ですの。これでログイン状態をアプリに教えてくれるの！



### ステップ1：Contextを作成するわよ💖
```tsx
const FirebaseUserContext = createContext<FirebaseUserContextType | undefined>(undefined);
```

これはまだ中身のない“箱”のようなものですの。
この箱にあとでログイン中のユーザー情報を入れて、みんなで使えるようにする準備をしておきますわあ💫

### ステップ2：Providerでユーザー情報を入れるのです⭐️

```tsx
const FirebaseUserProvider = ({ children }: { children: ReactNode }) => {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
      setUser(firebaseUser);
    });
    return () => unsubscribe();
  }, []);

  return (
    <FirebaseUserContext.Provider value={{ user }}>
      {children}
    </FirebaseUserContext.Provider>
  );
};
```
上記のコードの
```tsx
 <FirebaseUserContext.Provider value={{ user }}>
 ```
ここで情報をcontextに入れてるのよ💖

### Step 3：アプリ全体をProviderで包むのですわ
```tsx
// _app.tsx（Next.jsの場合）
import { FirebaseUserProvider } from './FirebaseUserProvider';

function MyApp({ Component, pageProps }) {
  return (
    <FirebaseUserProvider>
      <Component {...pageProps} />
    </FirebaseUserProvider>
  );
}
```
🎀 Reactでは、Providerでラップされた中のすべての子コンポーネントは、そのContextを使えるようになるのですの！

これは、ReactのContextが **「親から子に見えないバトンを渡している」** 仕組みだからですわ✨


### Step 4：子コンポーネントで Context から user を取り出す
```tsx
// Header.tsx
import { useFirebaseUser } from './FirebaseUserContext';

const Header = () => {
  const { user } = useFirebaseUser();

  return (
    <p>
      {user ? `${user.displayName} さん、ようこそ！` : 'ログインしてくださいませ'}
    </p>
  );
};
```
📌 どこにいても useFirebaseUser() を使えば user にアクセスできるのが魅力ですの💖
>※ useFirebaseUser() は Context をカスタムフック化したものですの。定義しておくと使いやすくなりますわ！
以下がuseFirebaseUser()　の例
```tsx
// FirebaseUserContext.tsx
export const useFirebaseUser = () => {
  const context = useContext(FirebaseUserContext);
  if (!context) throw new Error('useFirebaseUser must be used within a FirebaseUserProvider');
  return context;
};
```



#### 💥 よくあるつまづきポイントとその解決法ですの

| 🌀 現象                     | 💡 原因と対処                                                                |
| ------------------------- | ----------------------------------------------------------------------- |
| `user` が `null` のまま       | 認証状態がまだ取得できていないだけ。<br>→ ローディング画面を出して、少し待ちましょ🕰                          |
| `useContext` でエラーになる      | Providerで囲まれていない or 初期値の設定ミス。<br>→ Providerをちゃんと使えているか確認するのよ💖|
| UIが更新されない                 | `setUser()` の更新が反映されてない可能性。<br>→ 状態更新や再描画の流れをチェックですの                    |
| `auth/internal-error` が出る | すでにログイン中なのに、またログインしようとした。<br>→ `auth.currentUser` で確認して、処理をスキップ！！      |
| Googleアイコンで画像エラー          | Next.jsが外部画像を許可していない。<br>→ `next.config.js` にドメインを追加ですの                 |
| ContextとProviderの関係がわからない | Providerが渡した `value` を Contextが受け取ってる。<br>→ `value={{ user }}` がキモですの⭐️   |
| ログインしてない状態の判定ができない        | `user === null` で未ログインってわかりますの。<br>→ 初期化で `onAuthStateChanged()` を使いましょ |
| ログイン直後の処理がうまくいかない         | `user` がまだ取得できてないことがある。<br>→ `await` や `auth.currentUser` で確認してから実行ですの  |


### 👑 最後に…

認証の実装って、最初は“なんで動かないの？”の連続ですの。ムカムカしてしまうのもしょうがないのよ
私もプリンセスながら、ちょくちょく出るエラー達にムカっとしてしまって一度myパソコンにデコピンしたくらいなのだからね🥺
でもそこで投げ出さずに向き合えた人だけが、アプリの土台を作れるのですわ💖
焦らず、何度でもチャレンジすれば、ちゃんと超えられる壁なのですの💪🌱

つまづいても、作り終えた自分の姿やアプリをユーザーに使ってもらっていることを妄想してテンションぶちあげで開発しましょ！！
折れてもいいけれど、続けることは辞めちゃダメよ🧚‍♂️

##
### 🔜 次回予告…✨
次回は、Firebase Authで実際にログイン機能を実装する方法を一緒にやっていきますの！
Googleログインの導入、ボタンUIの作成、ログインとログアウトの制御まで…！
「やってみたいけど難しそう…」そんな気持ちをゼロにして、一緒にステップ踏んでいきましょ💖

お楽しみに〜〜！🪄