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

home2 게시판 Next.js 게시판 좋아요 기능 질문드립니다.

좋아요 기능 질문드립니다.

4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 글쓴이
  • #98605
    안녕하세요. 선생님
    좋아요 체크, 좋아요 취소 둘의 기능을 구현하였는데
    문제가 있습니다.
    기능은 이렇습니다.
    
    1.상세페이지에 들어와있을때 좋아요가 눌러져 있다면 채워져있는하트, 아니면 빈하트
    (이 기능은 문제가 없습니다.)
    2. 좋아요 체크 
    3. 좋아요 취소(좋아요 체크되어있을 시 취소됨)
    4. 좋아요 누른 유저 목록 보여주기 (누른 유저가 없으면 가려짐)
    
    여튼... 문제는 이렇습니다.
    최종임
    상세 페이지에서 좋아요 체크, 취소를 하면 잘되지만(다른 링크로 이동안했을 경우)
    Link 에 걸려있는 홈이라든지, list 페이지로 이동한뒤 다시
    좋아요를 눌렀거나 취소를 했던 페이지(좋아요 눌렀거나 취소한 페이지)로 가면
    변화가 없습니다. (새로고침을 하면 정상반영이 됩니다.)
    
    서버에서 결과값을 보내줘서 그값을 state로 변경해주는 방식입니다.
    서버에서는 바뀐값이 정상으로 나옵니다
    상세페이지좋아요기능서버에서보여질때
    
    그러나 상세페이지 좋아요 버튼 기능 페이지에서는 이렇게 나옵니다.
    좋아요 체크를 눌렀을 시 나오는 콘솔 화면입니다.
    분명 서버에서 받은 값 result 를 출력하면 잘나옵니다만
    state 들을 출력해보면 이런식으로 나오네요...
    상세페이지좋아요누른뒤콘솔화면
    <--- 상세페이지 --->
    import { connectDB } from "@/util/database"
    import { MongoClient, ObjectId } from "mongodb"
    import Comment from './Comment'
    import PostLike from './PostLike'
    import { getServerSession } from "next-auth"
    import { authOptions } from "@/pages/api/auth/[...nextauth]"
    export default async function Detail(props){
        const client = await connectDB
        const db = client.db('forum')
        let result = await db.collection('post').findOne({_id : new ObjectId(props.params.id)})
        let session = await getServerSession(authOptions)
        let elementExis = null
        console.log(session.user)
        if(session){
            if(result.likeUser.includes(session.user.email)){ // 여기서 중복체크를 하여 좋아요 눌렀는지 여부 확인
                elementExis = true
            } else {
                elementExis = false
            }
        } else {
            console.log('비로그인')
        }
        return(
            <div>
                <h4>상세페이지</h4>
                <h4>{result.title}</h4>
                <p>{result.content}</p>
                <span>작성자 {result.name} - {result.author}</span>
                <PostLike result={result} name={result.name} _id={result._id} likeUser={result.likeUser} postLikeCount={result.postLikeCount} session={session} elementExis={elementExis}/>
                <Comment _id={result._id} />
            </div>
        )
    }
    <--- 상세페이지 좋아요 버튼 기능 페이지 --->
    'use client'
    import { useEffect, useState } from "react"
    export default function PostLike(props){
        let [heart, setHeart] = useState('🤍')
        let [auto, setAuto] = useState(props.elementExis)
        useEffect(()=>{
            if(auto === null || auto === false){
                console.log('좋아요 안눌러져 있을 때')
                setHeart('🤍')
            } else if (auto === true){
                console.log('좋아요 눌러져 있을 때')
                setHeart('❤️')
            }
        },[])
        let [likeUserList, setLikeUserList] = useState(props.likeUser)
        let [likeCount, setLikeCount] = useState(props.postLikeCount)
        let [trg, setTrg] = useState(false)
        // let [err, setErr] = useState(true)
        let res = null
        return(
            <div>
                <div>
                    {likeCount < 1 ? null : <p>{likeCount} 명이 좋아합니다.</p>}
                    <span>좋아요</span>
                    <button onClick={(e)=>{
                        {
                            if(auto === null || auto === false){ // 좋아요 안눌러저 있을 때
                                console.log('좋아요 안눌러져 있을 때')
                                fetch('/api/like/likePlus',{
                                    method : "POST",
                                    body : JSON.stringify({likeCount : likeCount, _id : props._id, name : props.name})
                                }).then((response)=>{
                                    if(response.status === 200){
                                        res = true
                                        return response.json()
                                    } else {
                                        res = false
                                        return response.json()
                                    }
                                }).then((result)=>{
                                    if(res === true){ // 로그인 세션 존재 하면
                                        setAuto(true)
                                        setHeart(result[0])
                                        setLikeUserList(result[1])
                                        setLikeCount(result[2])
                                        console.log('좋아요 체크')
                                    } else { // 로그인 세션 존재 하지 않으면
                                        setErr('권한이 없습니다.')
                                    }
                                }).catch((error)=>{
                                    console.log(error)
                                })
                            } else if(auto === true){ // 좋아요 눌러저 있을 떄
                                console.log('좋아요 눌러져 있을 때')
                                fetch('/api/like/likeMinus', {
                                    method : "POST",
                                    body : JSON.stringify({likeCount : likeCount, _id : props._id, name : props.name})
                                }).then((response)=>{
                                    if(response.status === 200){
                                        res = true
                                        return response.json()
                                    } else {
                                        res = false
                                        return response.json()
                                    }
                                }).then((result)=>{
                                    if(res === true){
                                        setAuto(false)
                                        setHeart(result[0])
                                        setLikeUserList(result[1])
                                        setLikeCount(result[2])
                                        console.log('좋아요 취소')
                                    } else {
                                        setErr('권한이 없습니다.')
                                    }
                                }).catch((error)=>{
                                    console.log(error)
                                })
                            }
                        }
                    }}>{heart}</button>
                    {likeCount < 1 ? null : <button onClick={()=>{
                        setTrg(!trg)
                    }}>좋아요 목록</button>}
                    {trg === false ? null : <ListOne likeUserList={likeUserList}/>}
                    {/* {err === false ? null : <ErrPopup err={err} />  } */}
                </div>
                <button onClick={()=>{
                }}>근황버튼</button>
            </div>
        )
    }
    function ListOne(props){
        return(
            <div>
             
      <li style="list-style-type: none;">
                      {                     props.likeUserList.map((a, i)=>{                         return(                             <li key={i}>{a}

                            )                     })                 }            

            </div>     ) } <--- 좋아요 체크 서버 api --->

    import { connectDB } from "@/util/database"
    import { getServerSession } from "next-auth"
    import { authOptions } from "../auth/[...nextauth]"
    import { ObjectId } from "mongodb"
    export default async function handler(req, res){
        let session = await getServerSession(req, res, authOptions)
        if(req.method === 'POST'){
            if(session){
                req.body = JSON.parse(req.body) 
                let client = await connectDB
                let db = client.db('forum')
                let result = await db.collection('user_cred').findOne({email : session.user.email})
                let save = {
                    user : session.user.name, // 좋아요 누른 유저의 이름
                    userLike_id : new ObjectId(result._id), // 좋아요 누른 유저의 _id
                    postUser : req.body.name, // 해당 글 작성자 이름
                    postLike_id : new ObjectId(req.body._id) // 해당 글의 _id
                }
                console.log(req.body)
                let result2 = await db.collection('post').findOne({_id : new ObjectId(save.postLike_id)})
                let arrUser = {likeUser : session.user.email} // 현재 좋아요 누른 유저의 이메일 정보
                let countPlus = {postLikeCount : 1} // 1증가
                try{
                    await db.collection('post').updateOne({_id : new ObjectId(result2._id)}, {$push : arrUser})
                    await db.collection('post').updateOne({_id : new ObjectId(result2._id)}, {$inc : countPlus})
                    await db.collection('postlike').insertOne(save)
                    let countRe = await db.collection('post').findOne({_id : new ObjectId(result2._id)}) // 좋아요 수 출력
                    console.log(countRe)
                    return res.status(200).json(['❤️', countRe.likeUser, countRe.postLikeCount])
                } catch{
                    return res.status(500).json('서버 오류')
                }
            } else {
                return res.status(400).json('권한이 없습니다.')
            }
        } else {
            return res.status(400).json('잘못된 접근입니다.')
        }
    }
    
    <--- 좋아요 취소 서버 api --->
    
    import { connectDB } from "@/util/database";
    import { authOptions } from "../auth/[...nextauth]";
    import { getServerSession } from "next-auth";
    import { ObjectId } from "mongodb";
    export default async function(req, res){
        if(req.method === "POST"){ // POST 로 받았을 때
            let session = await getServerSession(req, res, authOptions) // 현재 로그인한 세션
            if(session){ // 세션이 존재하는가 ?
                req.body = JSON.parse(req.body)
                let client = await connectDB
                let db = client.db('forum')
                let result = await db.collection('user_cred').findOne({email : session.user.email})
                let minusSave = {
                    user : session.user.name, // 좋아요 누른 유저의 이름
                    userLike_id : new ObjectId(result._id), // 좋아요 누른 유저의 _id
                    postUser : req.body.name, // 해당 글 작성자 이름
                    postLike_id : new ObjectId(req.body._id) // 해당 글의 _id
                }
                let result2 = await db.collection('post').findOne({_id : new ObjectId(minusSave.postLike_id)})
                let arrUser = {likeUser : session.user.email} // 현재 좋아요 누른 유저의 이메일 정보
                let countPlus = {postLikeCount : -1} // 1감소
                
                try {
                    await db.collection('post').updateOne({_id : new ObjectId(result2._id)}, {$pull : arrUser})
                    await db.collection('post').updateOne({_id : new ObjectId(result2._id)}, {$inc : countPlus})
                    await db.collection('postlike').deleteOne(minusSave)
                    let countRe = await db.collection('post').findOne({_id : new ObjectId(result2._id)}) // 좋아요 수 출력
                    console.log(countRe)
                    return res.status(200).json(['🤍',countRe.likeUser, countRe.postLikeCount])
                } catch {
                    return res.status(500).json('실패')
                }
            }
        } else { // POST 외에 다른 요청으로 받았을 때 실패
            return res.status(400).json('잘못된 접근입니다.')
        }
    }
    #98617

    codingapple
    키 마스터
    props를 다시 useState에 넣어서 쓰면 안되고 그냥 씁시다 
    근데 좋아요처리하는 서버기능에서 이미 이메일이 거기 array안에 있으면 $push 하지말라는 로직도 추가해야할듯요
    #98696
    선생님 "props를 다시 useState에 넣어서 쓰면 안되고 그냥 씁시다" 이말이 이해가 안되서
    그러는데요 props를 useState 초기값으로 사용하면 안된다는 말씀이신가요?
    
    
    #98717

    codingapple
    키 마스터
    넴 그럼 이상해집니다
4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 답변은 로그인 후 가능합니다.

About

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

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

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