🐥
Firebase Authenticationのログイン状態を管理する
はじめに
今回初めてfirebase Authenticationを使ってログイン機能を作りました。
どのようにログイン状態を管理したのかを備忘録としてまとめます。
今回はログイン状態をContextでグローバルなStateとして管理しました。
環境
- TypeScript
- Next.js
実装
まずはContextを利用するためにProviderコンポーネントをつくります。
currentUserがログイン状態を表すstateです。
currentUserにユーザー情報が入っていればログインしていることを表し、値が入っていなければログインしていないことになります。
useEffectの中でログイン状態を確認します。
firebase AuthenticationではonAuthStateChanged関数でログインしているユーザーの情報を確認できます。ユーザーが存在していればstateにセットします。
このonAuthStateChanged関数ですがAuthオブジェクトの初期化に時間がかかるためonAuthStateChangedが呼び出されるまでに少し時間がかかります。
よってここではsignInCheckというstateでログイン状態を確認したかどうかを管理しました。
signInCheckがfalseの時、つまりログイン状態の確認ができていない間はローディング中であることを表示するLoadingコンポーネントを表示させることにしました。
Providerコンポーネントのコードはこのようになりました
auth/AuthProvider.tsx
import firebase from "firebase/app";
import { createContext, useEffect, useState, VFC, ReactNode } from "react";
import { auth, db } from "../firebase";
export type User = firebase.User;
type AuthContextProps = {
currentUser: User | null | undefined;
signInCheck: boolean;
};
const AuthContext = createContext<AuthContextProps>({
currentUser: undefined,
signInCheck: false,
});
const AuthProvider: VFC<Props> = ({ children }) => {
const [currentUser, setCurrentUser] =
useState<User | null | undefined>(undefined);
const [signInCheck, setSignInCheck] = useState(false);
// ログイン状態を確認する
useEffect(() => {
auth.onAuthStateChanged(async (user) => {
if (user) {
setCurrentUser(user);
setSignInCheck(true);
} else {
setSignInCheck(true);
}
});
});
if (signInCheck) {
return (
<AuthContext.Provider value={{ currentUser, signInCheck }}>
{children}
</AuthContext.Provider>
);
} else {
// ログイン確認中
// 自分で作ったローディングコンポーネントをレンダリングする
return <Loading />;
}
};
export { AuthContext, AuthProvider };
そしてログイン状態を各コンポーネントから使えるようにするためにProviderコンポーネントで全体を囲みます。
pages/_app.tsx
const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => {
return (
<>
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
</>
);
};
ユーザー情報を使いたいページでは
const {currentUser} = useContext(AuthContext)
のようにしてユーザー情報にアクセスできます。
Discussion
setSignInCheck
がどちらもtrueになっていますが、間違いでしょうか?signInCheckはログインを状態を確認したかを判別する値なので、最終的にはtrueになるため、どちらもtrueになるのが正しいと思います!
以下のコードの方が分かりやすいかもしれません!
ご回答ありがとうございます!
なるほどそういうことですか。