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

PostDetail.jsの作成

PostDetail.js
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import {doc, getDoc} from 'firebase/firestore';
import { db } from './FireBase';
import ShareButtons from './ShareButtons';

function PostDetail() {
  const { postId } = useParams();
  const [post, setPost] = useState(null);
  console.log("postId:", postId);
  const [author, setAuthor] = useState(null);

	//Firestoreのposts/{postId}ドキュメントを取得。
	//存在する場合、対応するユーザー情報も取得。
	//両方を setPost, setAuthor でステートに保存。
  useEffect(() => {
    const fetchPost = async () => {
      const postDoc = await getDoc(doc(db, 'posts', postId));
      if (postDoc.exists()) {
         const postData = postDoc.data();
         setPost(postData);

         const userDoc = await getDoc(doc(db, 'users', postData.uid));
         if (userDoc.exists()) {
          setAuthor(userDoc.data());
         }
      } else {
        console.warn("投稿が存在しません");
      }
    };
    fetchPost();
  }, [postId]);
  
  if (!post) return <p>読み込み中...</p>;

  const shareUrl = `${window.location.origin}/post/${postId}`;
  console.log("共有URL:", shareUrl);
  const shareTitle = `Keruma SNSで面白い投稿を見つけました!「${post.text?.slice(0,30)}...」`;

  return (
    <div className="max-w-2xl mx-auto p-6 mt-10 bg-white shadow rounded">
      <div className="flex items-center mb-4">
        <img
          src={author?.photoURL || '/default-icon.png'}
          alt="ユーザーアイコン"
          className="w-10 h-10 rounded-full mr-2"
        />
        <div>
          <p className="font-semibold">{author?.name || '匿名ユーザー'}</p>
          <p className="text-sm text-gray-500">{post.time}</p>
        </div>
      </div>

      <p className="mb-4">{post.text}</p>

      {post.imageUrl && (
        <img src={post.imageUrl} alt="投稿画像" className="rounded-md mb-4 max-w-full"/>
      )}

      {post.videoUrl && (
        <video controls className="rounded-md mb-4 max-w-full">
           <source src={post.videoUrl} type="video/mp4"/>
        </video>
      )}

      <ShareButtons url={shareUrl} title={shareTitle}/>

      <div className="mt-6">
          <h3 className="font-semibold">コメント一覧</h3>
          <ul className="list-disc list-inside mt-2">
            {(post.comments || []).map((c, i) => (
              <li key={i}>{c}</li>
            ))}
          </ul>
      </div>
    </div>
  );

}

export default PostDetail;

AppRouter.jsにパスを設定

AppRouter.js
import PostDetail from './PostDetail';

<Route path="post/:postId" element={<PostDetail />} />

プロフィール画面・投稿一覧画面にクリックイベントを記述

    <div
      className="cursor-pointer"
      onClick={() => navigate(`/post/${post.id}`)}
    >

    //投稿内容を上記onClickで囲む
    
      </div>
    

投稿詳細画面UI

スクリーンショット 2025-05-31 8.23.02.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?