概要
Firebase Autheticationを使ったログインをアプリに組み込んでみました。
その際の実装方法に関する備忘録です。
環境
- NextJS 14.2.5
- Page Router
- Firebase 10.12.3
やってみた
/libs/firebase
.ts を作成しました。
コードは以下です。
import { getApps, initializeApp } from 'firebase/app';
const firebaseConfig = {
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_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
export const getApp = () => {
const apps = getApps();
if (apps.length === 0) {
return initializeApp(firebaseConfig);
}
return apps[0];
};
上記関数を呼び出すコードの例は以下です。
サンプルとして記載したのは新規登録処理で使う場合のコードです。
import { AuthContext } from '@/contexts/firebaseProvider';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import {
Alert,
Avatar,
Box,
Button,
Container,
Grid,
Snackbar,
TextField,
Typography,
} from '@mui/material';
import { createUserWithEmailAndPassword, getAuth } from 'firebase/auth';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useContext, useState } from 'react';
// getAppをimport
import { getApp } from '@/libs/firebase';
import type { FirebaseError } from 'firebase/app';
export default function SignUp() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const { setUser } = useContext(AuthContext);
const router = useRouter();
// 取得する
const app = getApp();
const auth = getAuth(app);
const handleSubmit = () => {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
setUser(userCredential);
router.push('/task');
})
.catch((error: FirebaseError) => {
switch (error.code) {
case 'auth/invalid-email':
setError('メールアドレスが無効です。');
break;
case 'auth/missing-password':
setError('パスワードが無効です。');
break;
case 'auth/email-already-in-use':
setError('メールアドレスが既に使用されています。');
break;
default:
setError('登録に失敗しました。');
break;
}
});
};
const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value);
};
const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
const handleClose = () => {
setError('');
};
return (
<Container component="main" maxWidth="xs">
<Snackbar open={!!error} autoHideDuration={6000} onClose={handleClose}>
<Alert severity="error" onClose={handleClose}>
{error}
</Alert>
</Snackbar>
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
新規登録
</Typography>
<Box sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
onChange={handleEmailChange}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="new-password"
onChange={handlePasswordChange}
/>
</Grid>
</Grid>
<Button
type="button"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
onClick={handleSubmit}
>
登録する
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
<Link href="/">ログイン画面に戻る</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
}
初期化されていないときは初期化が実行され、初期化されている場合はインスタンスを返します。getApps
に似た関数として getApp
があるのですが、こちらは初期化されていない場合に呼び出すと例外を発生させます。
こちらでもよかったのですが、例外だと可読性が下がるので初期化の確認目的では getApps
のほうが良いと思います。
感想
実装方法は自分がReactに慣れていないこともあり結構苦戦しました。
Fireabaseのチュートリアルで使われている以下リポジトリのおかげで何とか実装までたどり着きました。
チュートリアルに感謝🙏
GitHub - firebase/friendlyeats-web
Contribute to firebase/friendlyeats-web development by creating an account on GitHub.
チュートリアルは以下です。
Firebase を Next.js アプリと統合する
Firebase を Next.js アプリと統合する方法について説明します。
個人で考えるだけではかなり苦戦しており、このチュートリアルがなければいい感じの実装までたどり着きませんでした。
これからも精進していきます🫡
コメント