0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ChatGPTを使用したアプリ開発記【投稿詳細画面でコメント表示・編集するように改修】

Posted at

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の構成

スクリーンショット 2025-06-01 10.30.09.png

投稿一覧画面ではコメント数のみ表示

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

スクリーンショット 2025-06-01 10.24.46.png

投稿詳細画面のコード

• 目的: 投稿に紐づくすべてのコメントを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>
)}

投稿詳細UI

スクリーンショット 2025-06-01 10.26.06.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?