Firestoreにコメントのサブコレクションのルールを追加
match /posts/{postId} {
allow read: if true;
allow write: if request.auth != null;
// 🔽 コメントのサブコレクションのルール
match /comments/{commentId} {
allow read, write: if request.auth != null;
}
}
Firestoreの構成
投稿一覧画面ではコメント数のみ表示
Home.js
// Firestore の posts コレクションの中にある、ある投稿 (docSnap.id) に対応するサブコレクション comments を指定しています。
const commentsSnapshot = await getDocs(collection(db, "posts", docSnap.id, "comments"));
// 取得した commentsSnapshot の中に含まれるコメント数(ドキュメント数)を返します
const commentCount = commentsSnapshot.size;
//コメント数の表示
<div style={{ marginTop: '1rem' }}>
<p className="text-sm text-gray-600">
コメント数: {post.commentCount || 0}
</p>
</div>
投稿一覧画面UI
投稿詳細画面のコード
• 目的: 投稿に紐づくすべてのコメントをFirebase Firestoreから取得。
• コレクション構造:
Firestoreでは、投稿(posts)の中に、サブコレクションとしてcommentsがある構造。
PostDetail.js
const commentsSnapshot = await getDocs(collection(db, 'posts', postId, 'comments'));
const commentsList = commentsSnapshot.docs.map(doc => doc.data());
setComments(commentsList);
• 目的: 取得したcommentsを画面に表示。
• userNameとtextをリスト形式で表示。
• comments.length === 0 のときは「コメントはまだありません」と表示。
PostDetail.js
{comments.length === 0 ? (
<p className="text-gray-500">コメントはまだありません。</p>
) : (
<ul className="list-disc list-inside mt-2 mb-4">
{comments.map((c, i) => (
<li key={i}>
<span className="font-bold">{c.userName || '匿名'}:</span> {c.text}
</li>
))}
</ul>
)}
• 目的: 投稿に新しいコメントを追加する。
• commentText(テキストエリアの入力内容)が空でなく、ログイン済みなら処理実行。
• usersコレクションからユーザー名を取得。
• 新しいコメントデータ(text, userId, userName, createdAt)を構築。
• addDocでFirestoreのcommentsサブコレクションに追加。
• 成功後はコメントをローカル状態にも追加し、入力欄を空にする。
PostDetail.js
const handleAddComment = async () => {
if (!commentText.trim() || !currentUser) return;
const userDoc = await getDoc(doc(db, 'users', currentUser.uid));
const userName = userDoc.exists() ? (userDoc.data().name || "匿名") : "匿名";
const newComment = {
text: commentText.trim(),
userId: currentUser.uid,
userName,
createdAt: serverTimestamp(),
};
try {
await addDoc(collection(db, 'posts', postId, 'comments'), newComment);
setComments(prev => [...prev, newComment]); // 即座にUIにも追加
setCommentText(""); // 入力欄を空にする
} catch (err) {
console.error("コメントの送信に失敗:", err);
}
};
• ログイン状態によって表示内容が切り替わる。
• ログイン済み: テキストエリアと送信ボタンを表示。
• 未ログイン: ログインが必要という案内メッセージを表示。
PostDetail.js
{currentUser ? (
<div className="mt-4">
<textarea
rows={2}
value={commentText}
onChange={(e) => setCommentText(e.target.value)}
placeholder="コメントを入力..."
className="w-full p-2 border rounded focus:outline-none focus:ring"
/>
<button
onClick={handleAddComment}
className="mt-2 bg-blue-500 text-white px-4 py-2 rounded-2xl hover:bg-blue-600 transition duration-200 shadow-md"
>
コメントする
</button>
</div>
) : (
<p className="text-gray-500">コメントするにはログインが必要です。</p>
)}