[ react ] 게시글 상세 페이지 & 조회수

Suji Kang·2023년 11월 6일
0
post-custom-banner

🐾 데이터에 있는거 가져오기

먼저 만들어야할 state 변수가 6개가있다.

그런데, state 변수를 다 만들기는 너무많고 귀찮다..
객체로 만들어보자❗️
한번에 몰아서 이 객체를 변수에 저장하겠다.

activity.likeCnt
activity.writerEmail
activity.createdDate 이런형태로 가져옴.

하지만❗️ 아직 data에서 받아온거 없으니깐 null 값으로 바꿔준다.

📌 "?" 연산자

최초로 그려질때 처음에 값은 null 이니까, 보여줄게없어서 오류가 난다. 원래는 activity가 null결과가 나오면 오류가 나는데, 그래서, ? 를 사용하면 오류가 나오지않고, undefined 이 나온다.

activity가 null이 아닐때만, 보여준다.

{activity.title !== null && activity.title}
{activity?.title}

?물음표를 안쓰면 오류가 난다. 처음값이 null 이기떄문에, 물음표를 사용함으로써.


10개 하나하나 다 쓰기는 너무 귀찮잖아. 언제 다써?

🐾 전개연산자 '...'

그래서 ...activity -> activity 풀어주는 역할.

  • 배열에서 사용 가능
  • 객체에서 사용 가능

배열 예시

let ar = [ 10, 20, 30 ];
let ar2 = [ 0, ...ar , 90 ] ; // ar2 : 
ar2[0] = 100;
    // ar2 : [100, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    // ar : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

객체 예시

let book = { title:'대모험', page: 20, author:'홍길동' }
let book2 = { title:book.title, page:book.page, author:book.author };
let book2 = { ...book , price:100 , title:'홍길동전'};

title이 두개면, 마지막것으로 덮어쓴다. 그래서 대모험은 사라지고 홍길동전생김.

새로운객체를 만들어줘.!
...activity는 그전 거 그대로 나오고,

setActivity({ ...activity ,
liked:'no', 
activity_like : activity.activity_like - 1});
 const onLikeClick = async ()=>{
        if(activity.liked === 'yes'){
            try{
                await axios.delete('/api/like', {
                    data:{id:activity.id},
                    headers:{Authorization:`Bearer ${accessToken}`}
                    
                });
                setActivity({ ...activity , liked:'no', activity_like : activity.activity_like - 1});

            }catch(err){
                console.log(err);
                alert('좋아요 현재 수정 불가');
            }
        }else{
            try{
                await axios.post('/api/like', 
                    {id:activity.id}, 
                    {headers:{Authorization:`Bearer ${accessToken}`}}
                );
                setActivity({...activity , liked:'yes', activity_like:activity.activity_like+1});

            }catch(err){
                console.log(err);
                alert('좋아요 오류');
            }
        }
    }

아이디가 1번인거를 먼저 조회를 한다.

 try{
    let sql = `
      select activity_view
      from tbl_activities
      where id = ?;
    `;
    let [ views ] = await pool.query(sql, [id]); //현재 조회수를 가져와서,

    sql =`
      update tbl_activities
      set activity_view = ?
      where id = ?;
    `;
    await pool.query(sql, [ views[0].activity_view + 1 , id]) //현재조회수에서 더하기 1 한값을 구해줘. 
                          //views[0].activity_view 👉 현재조회수를 뜻함

새로고침할때마다 올라가게 안하고,
ip 주소를 받아와서 아이피주소가 본적없는것만 확인해서 그걸고 조회수가 올라가게 할수있다.

owner 이면 보고 아니면 안보이고

{
        activity?.owner &&
         <div
          style={{
              alignSelf: 'flex-end',
              display: 'flex',
              columnGap: '10px'
                }}>
             <WriteBtn>수정하기</WriteBtn>
             <WriteBtn
                style={{ backgroundColor: 'red' }}>삭제하기
             </WriteBtn>
          </div>
}

activityDetailSection.js

const ActivityDetailSection = (props) => {

    const [activity, setActivity] = useState(null); //게시글 정보

    const { accessToken } = useContext(UserContext);

    useEffect(() => {
        let tmp = async () => {
            if (accessToken === null) return;
            try {
                let res = await axios.get(`/api/activities/${props.activityId}`, {
                    headers: { Authorization: `Bearer ${accessToken}` }
                });
                setActivity(res.data); //조회수증가
                // setIsLiked(res.data.liked === 'yes');
            } catch (err) {
                console.log(err);
                alert('오류가 발생했어요.')
            }
        }

        tmp();
    }, [props.activityId, accessToken]);

    const onLikeClick = async () => {
        if (activity.liked === 'yes') {
            try {
                await axios.delete('/api/like', {
                    data: { id: activity.id },
                    headers: { Authorization: `Bearer ${accessToken}` }

                });
                setActivity({ ...activity, liked: 'no', activity_like: activity.activity_like - 1 });

            } catch (err) {
                console.log(err);
                alert('좋아요 현재 수정 불가');
            }
        } else {
            try {
                await axios.post('/api/like',
                    { id: activity.id },
                    { headers: { Authorization: `Bearer ${accessToken}` } }
                );
                setActivity({ ...activity, liked: 'yes', activity_like: activity.activity_like + 1 });

            } catch (err) {
                console.log(err);
                alert('좋아요 오류');
            }
        }
    }
    return (
        <section>
            <BoardDetailWrap>
                <BoardTitle>
                    {activity?.title}
                    <div style={{ display: 'flex', alignItems: 'baseline' }}>
                        <span>좋아요:{activity?.activity_like} </span>
                        <span onClick={onLikeClick}>
                            {activity?.liked === 'yes' ? <FavoriteIcon style={{ color: 'red' }} /> : <FavoriteBorderIcon />}
                        </span>
                    </div>
                </BoardTitle>
                <BoardInfoWrap>
                    <p>작성자</p>
                    <p>{activity?.writer_email}</p>
                    <p>조회수</p>
                    <p>{activity?.activity_view}</p>
                </BoardInfoWrap>
                <BoardInfoWrap>
                    <p>작성일자</p>
                    <p>{activity?.created_date}</p>
                    <p>수정일자</p>
                    <p>{activity?.updated_date}</p>
                </BoardInfoWrap>
                <BoardContent>
                    {activity?.img_url.map((img) => <div>
                        <img style={{ width: '100%' }} src={img} alt="이미지" />
                    </div>)}
                    {activity?.content}
                </BoardContent>
                {
                    activity?.owner &&
                    <div
                        style={{
                            alignSelf: 'flex-end',
                            display: 'flex',
                            columnGap: '10px'
                        }}>
                        <WriteBtn>수정하기</WriteBtn>
                        <WriteBtn
                            style={{ backgroundColor: 'red' }}>삭제하기
                        </WriteBtn>
                    </div>}
            </BoardDetailWrap>
        </section>
    )
}
export default ActivityDetailSection;


profile
나를위한 노트필기 📒🔎📝
post-custom-banner

0개의 댓글