ログイン機能の実装
(1)Firebaseプロジェクトを作る
1.Firebase Console でプロジェクト作成
2.「Authentication」→「ログイン方法」→以下を有効化:
- メール/パスワード
(2) Firebase設定ファイル作成(firebase.js)
firebase.js
// Firebase アプリの初期化に必要な関数をインポートします。
// これにより、Firebase プロジェクトと React アプリが接続されます。
import { initializeApp } from "firebase/app";
// irebaseの認証機能に関する関数やクラスをインポートします。
// getAuth → Firebase認証システムを使用するための関数
// GoogleAuthProvider → Googleログインのためのプロバイダー(設定)
import { getAuth, GoogleAuthProvider } from 'firebase/auth';
// あなたのFirebaseプロジェクトと通信するための設定情報です。
// Firebaseのコンソールからコピーした構成情報がここに入ります。
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
// Firebaseアプリを初期化します。
// このコードにより、上記の構成情報で Firebase を使う準備が整います。
const app = initializeApp(firebaseConfig);
// 認証システムのインスタンスを生成し、他ファイルでも使えるように「export(外部公開)」します。
// 他のファイル(たとえば Login.js)からこの auth を使ってログイン操作ができます。
export const auth = getAuth(app);
// Googleログインを行うための「プロバイダーオブジェクト」を生成し、他ファイルでも使えるように公開します。
// このオブジェクトを使って、Googleログインができるようになります。
export const googleProvider = new GoogleAuthProvider();
(3)ログイン画面コンポーネントの作成
login.js
// Reactの基本機能と、コンポーネント内で状態(state)を持つための useState フックを読み込んでいます。
import React, { useState } from 'react';
// firebase.js でエクスポートした Firebase 認証インスタンスと Googleログイン用プロバイダーを読み込みます。
import { auth, googleProvider } from './firebase';
// Firebase Authentication のログイン/登録機能に必要な関数を読み込んでいます。
import {
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signInWithPopup,
} from 'firebase/auth';
// Login コンポーネントの定義です。
// 親コンポーネント(App.js)から onLogin 関数を受け取っています。ログイン成功後に実行します。
function Login({ onLogin }) {
// メールアドレスとパスワードの入力状態(state)を管理しています。
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const loginEmail = async () => {
try {
await signInWithEmailAndPassword(auth, email, password);
onLogin();
} catch (e) {
alert(e.message);
}
};
const signupEmail = async () => {
try {
await createUserWithEmailAndPassword(auth, email, password);
onLogin();
} catch (e) {
alert(e.message);
}
};
const loginGoogle = async () => {
try {
await signInWithPopup(auth, googleProvider);
onLogin();
} catch (e) {
alert(e.message);
}
};
return (
<div>
<h2>ログイン/登録</h2>
<input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="メール" />
<p><input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="パスワード" /></p>
<div>
<button onClick={loginEmail}>ログイン</button>
<button onClick={signupEmail}>登録</button>
<button onClick={loginGoogle}>Googleでログイン</button>
</div>
</div>
);
}
export default Login;
(4)Appコンポーネントに認証統合
App.js
// Reactの状態管理(useState)と副作用処理(useEffect)を使う準備です。
// useEffectは、関数コンポーネントで副作用(DOM操作、API通信など、UI以外で処理を行うこと)を管理するためのフックです。
import React, { useState , useEffect} from 'react';
// Firebase の認証状態監視とログアウト処理をする関数を読み込みます。
import { auth } from './firebase';
// firebase.js から Firebase 認証インスタンスを読み込みます。
import { onAuthStateChanged, signOut } from 'firebase/auth';
// 自作の Login.js コンポーネントを読み込みます(ログイン画面)。
import Login from './login';
function App() {
// 現在ログインしているユーザーを保持するための state です。未ログイン時は null。
const [user, setUser] = useState(null);
const [text, setText] = useState('');
const [posts, setPosts] = useState([]);
// Firebase のログイン状態を常に監視します。
useEffect(() => {
// user がログインしていれば setUser(user) で状態更新
const unsub = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
return () => unsub();
}, []);
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim() === '') return;
const now = new Date();
const formattedTime = now.toLocaleString('ja-JP', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
const newPost = {
text: text,
time: formattedTime,
likes: 0,
user: user?.email,
};
setPosts([newPost, ...posts])
setText('');
};
const handleLike = (index) => {
const updated = [...posts];
updated[index].likes += 1;
setPosts(updated);
}
const handleDelete = (index) => {
setPosts(posts.filter((_, i) => i !== index));
};
// ユーザーが未ログインなら、ログイン画面を表示します。
// ログイン成功時に setUser を実行することで、投稿画面に遷移します。
if (!user) {
return <Login onLogin={() => { }} />;
}
return (
<div style={{ padding: '2rem', fontFamily: 'sans-serif' }}>
<h1>SNS</h1>
<p>ようこそ、{user.email} さん <button onClick={() => signOut(auth)}>ログアウト</button></p>
<form onSubmit={handleSubmit}>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="今なにしてる?"
rows="4"
style={{ display: 'block', width: '100%', marginBottom: '1rem' }}
/>
<button type="submit">投稿する</button>
</form>
<div style={{ marginTop: '2rem' }}>
<h2>投稿一覧</h2>
{posts.map((post, index) => (
<div key={index} style={{ padding: '1rem', borderBottom: '1px solid #ccc' }}>
<div style={{ fontSize: '0.8rem', color: '#666' }}>{post.time} - {post.user}</div>
<div>{post.text}</div>
<button onClick={() => handleLike(index)}>❤️ いいね ({post.likes})</button>
<button onClick={() => handleDelete(index)} style={{ marginLeft: '1rem', color: 'red' }}>🗑️ 削除</button>
</div>
))}
</div>
</div >
);
}
export default App;