• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 Next.js 게시판 쌤 좋아요기능 구현좀 봐주세요

쌤 좋아요기능 구현좀 봐주세요

7 글 보임 - 1 에서 7 까지 (총 7 중에서)
  • 글쓴이
  • #81321

    정중식
    참가자
    좋아요 기능 api 입니다.
    
    
    import { connectDB } from '@/util/database';
    import { ObjectId } from 'mongodb';
    export default async function handler(req, res) {
      try {
        if (req.method === 'POST') {
          const db = (await connectDB).db('forum');
          const post = await db
            .collection('post')
            .findOne({ _id: new ObjectId(req.body.postId) });
          const isLike = await db
            .collection('postLike')
            .findOne({ likeUser: req.body.userName });
          if (isLike) {
            return res.status(400).json('이미 좋아요 누른 게시글입니다.');
          }
          const result = await db.collection('postLike').insertOne({
            likeUser: req.body.userName,
            postId: new ObjectId(req.body.postId),
          });
          res.status(200).json('좋아요 성공');
        }
      } catch (error) {
        console.log(error);
        return res.status(500).json('error:', error);
      }
    }
    
    PostLike.js 입니다. 클라이언트 컴포넌트로 좋아요버튼 분리했어요
    
    
    'use client';
    import { useEffect } from 'react';
    const PostLike = ({ postId, userName }) => {
      const onLikeBtnClick = () => {
        fetch('/api/post/like', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            postId,
            userName,
          }),
        }).then((data) => {
          if (data.status === 200) {
          } else if (data.status === 400) {
            alert('이미 좋아요 누른 게시물입니다.');
          }
        });
      };
      return (
        <div className='post-like-btn' onClick={() => onLikeBtnClick()}>
          <span>👍</span>
        </div>
      );
    };
    export default PostLike;
    Detail.js입니다. 서버컴포넌트이고 좋아요버튼 컴포넌트를 자식컴포넌트로 두고있어요.
    
    
    // dynamic route
    // (props)=>{}; 하고,
    // console.log(props); 해주면 유저가 다이나믹라우터 자리에입력한 값이 콘솔에뜸
    // 다이나믹라우터란?${id}를뜻함 전체에시=> localhost:3000:/detail/${id}
    import { connectDB } from '@/util/database';
    import { ObjectId } from 'mongodb';
    import Link from 'next/link';
    import Comment from './Comment';
    import PostLike from '../PostLike';
    import { getServerSession } from 'next-auth';
    import { authOptions } from '@/pages/api/auth/[...nextauth]';
    const Detail = async (props) => {
      const session = await getServerSession(authOptions);
      let client = await connectDB;
      const db = client.db('forum');
      let result = await db
        .collection('post')
        .findOne({ _id: new ObjectId(props.params.id) });
      let postLike = await db
        .collection('postLike')
        .find({ postId: new ObjectId(props.params.id) })
        .toArray();
      return (
        <div className='container'>
          <h4 className='title mt-2 mb-3 '>상세페이지</h4>
          {result && (
            <div className='list'>
              <div className='list-item'>
                <div className='emoticon-box'>
                  <Link href={`/edit/${result._id}`}>✏️</Link>❌
                </div>
                <h4>
                  <span>{result.title}</span>
                </h4>
                <span className='post-like-count'> ・ {postLike.length}</span>
                <p>{result.contents}</p>
                <PostLike postId={props.params.id} userName={session.user.name} />
                <Comment postId={result._id.toString()} />
              </div>
            </div>
          )}
        </div>
      );
    };
    export default Detail;
    
    여기까지했을때 잘됬습니다. 근데 궁금한게
    
    1. 좋아요 눌렀을때 실시간으로 좋아요 갯수가 올라가게해주려면 어떻게해야하나요? 그냥 새로고침을 해주는게 가장 나을까요? 
       디테일페이지를 똑같이 클라이언트 컴포넌트로 해주면되겠지만,.. 근데 만약 이 디테일페이지가 검색노출이 중요한페이지라고했을때가 문제가되서요
    
    2. 디테일페이지에서 좋아요 갯수를 출력해주고있어요 다음 사진처럼요
    
    디테일페이지말고 list페이지 그러니깐.. 전체 게시글에서 저렇게 좋아요갯수를 표시하게끔해주려면 어떻게 구현해줘야하나요?
    
    지금 현재 
    
    좋아요 도큐먼트를 만들어놨고 여기에
    좋아요한게시물, 좋아요한유저이름을 저장해놨고
    
    디테일페이지에서 좋아요도큐먼트를 찾는데, 조건은 좋아요한게시물의 아이디를 받아와서 그 갯수를 출력해주고있어요.
    이런식으로요
    
    
    const Home = async () => {
      let client = await connectDB;
      const db = client.db('forum');
      let result = await db.collection('post').find().toArray();
      result = result.map((data) => {
        data._id = data._id.toString();
        return data;
      });
      return (
        <div className='container'>
          {result.length === 0 ? (
            <h1 className='not-post'>현재 작성된 글이 없습니다.</h1>
          ) : (
            <PostList result={result} />
          )}
        </div>
      );
    };
    export default Home;
    근데 여기서 전체게시글들의 좋아요 갯수를 어떻게 출력해서 PostList컴포넌트한테 전달해줘야할까요?
    
    
    #81322

    정중식
    참가자
    올바르게 구현한건지 체크도 부탁드릴게요..
    #81334

    codingapple
    키 마스터
    잘될거같군요
    1은 새로고침하거나 클라이언트컴포넌트 씁시다 
    클라이언트 컴포넌트도 DB게시물 props로 보내줘서 미리 채워보내면 검색노출 잘될듯요 
    2 게시물 document마다 좋아요 갯수를 기록하는 란을 마련해두는게 어떨까요 그러면 편리할수도요
    #81368

    정중식
    참가자
    쌤 2번요, 이렇게 구현해봤어요
    
    글 좋아요 api쪽에 작성한거에요
    
    
    import { connectDB } from '@/util/database';
    import { ObjectId } from 'mongodb';
    export default async function handler(req, res) {
      try {
        if (req.method === 'POST') {
          const db = (await connectDB).db('forum');
          const isLike = await db
            .collection('postLike')
            .findOne({ likeUser: req.body.userName });
          if (isLike) {
            return res.status(400).json('이미 좋아요 누른 게시글입니다.');
          }
          const post = await db
            .collection('post')
            .findOne({ _id: new ObjectId(req.body.postId) });
          post.postLikeCount++;
          const newPost = await db
            .collection('post')
            .updateOne({ _id: new ObjectId(req.body.postId) }, { $set: post });
          const result = await db.collection('postLike').insertOne({
            likeUser: req.body.userName,
            postId: new ObjectId(req.body.postId),
          });
          res.status(200).json('좋아요 성공');
        }
      } catch (error) {
        console.log(error);
        return res.status(500).json('error:', error);
      }
    }
     
    사진은 저장되있는 디비 형태입니다.
    근데 postLikeCount:'0' 으로 초기에 저장해놨는데 글좋아요api에서 postLikeCount++; 해서 js 자동형변환일어나서 숫자로 저장됬는데요, 
    이거를 서버에 저장시킬땐 문자열로 저장시키는게좋을까요?
    #81400

    codingapple
    키 마스터
    1. 찾아서 2. +1 시켜서 3. 다시 저장하는거말고 
    $inc 연산자쓰면 document를 바로 +1 가능합니다 
    숫자로 저장합시다
    #81720

    정중식
    참가자
    감사합니다. 선생님 추가로 질문드리고싶은게 있습니다.
    
    1.
      const session = await getServerSession(authOptions); 을 이용해서 작성자와 로그인된 유저의 '뭐'가 같으면 글 삭제와 글 수정을 보여주게끔 하려고하는데요
      여기서 '뭐'가 같으면 보여주는게 좋을까요? 
      지금 현재 게시글에 author: 이메일 이렇게되어있는데, 이메일로 비교하는게 좋을까요? 아니면 그냥 게시글 작성할때 작성한 유저의 id를 도큐먼트에 같이저장해서 그걸 비교해서 하는게 나을까요?
    
    2. 
           if (session) {
            const db = (await connectDB).db('forum');
            const isLike = await db
              .collection('postLike')
              .findOne({ likeUser: session.user.name });
            if (isLike) {
              return res.status(400).json('이미 좋아요 누른 게시글입니다.');
            }
            const post = await db
              .collection('post')
              .updateOne(
                { _id: new ObjectId(req.body.postId) },
                { $inc: { postLikeCount: +1 } }
              );
            const newPost = await db
              .collection('post')
              .updateOne({ _id: new ObjectId(req.body.postId) }, { $set: post });
            const result = await db.collection('postLike').insertOne({
              likeUser: req.body.userName,
              postId: new ObjectId(req.body.postId),
            });
            res.status(200).json('좋아요 성공');
          } else if (!session || session === null) {
            res.status(400).json({ message: '로그인이 필요합니다.' });
          }
        }
     
    
    이런식으로 status 400이 두개들어가있고, 메시지를 따로 보여주게끔 해주고싶은데요
    클라이언트에서 어떤식으로 받아줘야 메시지를 따로보여줄수있을까요? 
    클라이언트에서 .then(data=>console.log(data);) 해주면 상태코드만보이고 서버에서 보낸 message는 안보이는거같습니다,.
    #81750

    codingapple
    키 마스터
    나중에 이메일이 바뀔일이 없을거같으면 이메일써도 됩니다 
    아마 첫째 .then이나 둘째 .then 둘 중 하나에서 메세지 나올걸요 
    
7 글 보임 - 1 에서 7 까지 (총 7 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠