🚀
jotaiとumijs,firebase authでログイン
忘れないうちにメモします。
jotaiとは?
とても使いやすい状態管理ライブラリです。
umijsとは?
nextのようなライブラリです。
next使ったことないですが、おそらく似たような機能を提供していると思われます。
こちらのライブラリの良いところはant designというUIフレームワークとの親和性が高いところです。
私が基本的にant designを使用しているため、こちらを使用しています。
ドキュメントが中国語なのでとっつきにくいですが、cursorで読み込ませたら英語も中国語も一緒なので、あまり関係なく使用できます。
コード
currentUser
を監視するauthguard.ts
を適用し、currentUser
に値が入った場合にRoutingするようにしています。
firebase-atom.ts
firebase-atom.ts
firebase-atom.ts
import { initializeApp } from 'firebase/app';
import { Auth, User, getAuth, onAuthStateChanged } from 'firebase/auth';
import { atom, getDefaultStore } from 'jotai';
import {firebaseConfig} from 'firebase-config';
const firebaseAppAtom = atom(initializeApp(firebaseConfig));
const authAtom = atom<Auth>((get) => {
const app = get(firebaseAppAtom);
return getAuth(app);
});
const currentUserAtom = atom<User | null>(null);
currentUserAtom.onMount = (set) => {
const auth = getDefaultStore().get(authAtom);
onAuthStateChanged(auth, (user) => {
set(user);
});
};
export { authAtom, currentUserAtom, firebaseAppAtom };
こちらではfirebaseをimplementしていきます。
currentUserAtom
がマウントされた際にauthを監視していくように書いています。
auth-guard.tsx
auth-guard.tsx
auth-guard.tsx
import { useAtom } from 'jotai';
import { Navigate, Outlet } from 'umi';
import { currentUserAtom } from './firebase-atom';
export default (props: any): JSX.Element => {
return (
<AuthGuard>
<Outlet />
</AuthGuard>
);
};
const AuthGuard = ({ children }: { children: React.ReactNode }) => {
const [user] = useAtom(currentUserAtom);
if (user) {
return <Outlet />;
} else {
return <Navigate to="/signin" />;
}
};
authguardです。currentUserを監視してその値がnullでないときに画面を出しわけるように書いています。
signin-page.tsx
signin-page.tsx
sigin-page.tsx
import { useNavigate } from '@/.umi/exports';
import { authAtom, currentUserAtom } from '@/wrappers/firebase-atom';
import { GoogleOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import { Auth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import { useAtom } from 'jotai';
import { useEffect } from 'react';
export const signOut = (auth: Auth) =>
auth.signOut().then(() => console.log('signed out'));
export const signIn = async (auth: Auth) => {
const provider = new GoogleAuthProvider();
const credential = await signInWithPopup(auth, provider);
};
const LoginScreen = () => {
const [auth] = useAtom(authAtom);
const [user] = useAtom(currentUserAtom);
const navigate = useNavigate();
useEffect(() => {
if (user) {
navigate('/');
}
}, [user]);
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
}}
>
<Button
type="primary"
icon={<GoogleOutlined />}
size="large"
onClick={() => signIn(auth)}
>
Googleでサインイン
</Button>
</div>
);
};
export default LoginScreen;
こちらではログイン処理をおこなっています。
Google SignInのみです。
signIn
に関しては既にcurrentUserを監視しているため、画面遷移は記述しません。
useEffect
でcurrentUser
が見つかったときはルート画面に遷移しています。
.umirc.ts
.umirc.ts
.umirc.ts
import { defineConfig } from 'umi';
export default defineConfig({
routes: [
{
path: '/',
component: 'index',
wrappers: ['@/wrappers/auth-guard'],
},
{
path: '/signin',
component: 'signin-page',
},
{
path: '/invoice',
component: 'invoice-page',
wrappers: ['@/wrappers/auth-guard'],
},
],
npmClient: 'pnpm',
});
こちらがミソ。auth-guardはサインイン画面には必要ないので削除します。
その他のページにはauth-guardを設定します。
以上です。
比較的簡単にAuthguardをすることができました。
ご意見などがございましたら是非教えて頂きたいです。
Discussion