
// 동작은 하는데 다시 봐야 함!
// prop으로 데이터를 받으면 업데이트가 안 되는 현상을
// 내부적으로 API 요청해서 렌더링마다 갱신하는 것으로 임시 해결
// useSwr이나 useQuery를 사용해서 리팩토링 해야할 듯
/*
부모 컴포넌트로부터 props으로 likes를 받으면 좋아요 했을 때 갱신되지 않는 현상
자식 컴포넌트의 상태가 바뀐다고 해서 부모 컴포넌트가 리렌더링되지 않기 때문인 걸로 추정됨
props으로 받지 않고 자식 컴포넌트에서 axios로 다시 요청해서 데이터를 받는 방법이 있고, 이벤트 핸들러만 전달해서 데이터를 부모 컴포넌트에서 갖는 방법이 있는데, API 함수 중복 호출을 막기 위해 후자가 나을 것으로 예상됨
useSwr이나 useQuery를 쓰면 이 문제가 쉽게 해결될 것으로 보임. 나중에 리팩토링 해보는 것도 좋을듯.
useEffect 안에서 state를 바꾸는 effect가 있는데 해당 state를 dependency 배열에 넣으면 무한 렌더링된다는 것을 잊지 말자!
*/
/* eslint-disable no-unused-vars */
import React, { useState, useEffect, useCallback } from 'react';
import { useParams, Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import FavoriteBorderOutlinedIcon from '@mui/icons-material/FavoriteBorderOutlined';
import CommentOutlinedIcon from '@mui/icons-material/CommentOutlined';
import FavoriteIcon from '@mui/icons-material/Favorite';
import { HiddenHeading } from '@/Components/Common';
import {
createLike,
deleteLike,
getUserInfo,
getPostDetails,
} from '@/apis/post';
import { getCookie } from '@/apis/token';
const Post = ({ image, content, comments }) => {
console.log('---------------------------------------- Component Rendered');
const { postId } = useParams();
const [isLiked, setIsLiked] = useState(false);
const [likeId, setLikeId] = useState(null);
const [likeCount, setLikeCount] = useState(0);
console.log('[state] isLiked : ', isLiked);
console.log('[state] likeId : ', likeId);
/* checkUserHasLiked */
const checkUserHasLiked = async () => {
console.log(
'---------------------------------------- checkUserHasLiked start',
);
const userId = getCookie('_id');
const { likes: userLikeList } = await getUserInfo(userId);
if (!userLikeList) {
return false;
}
const userLikeIndex = userLikeList.findIndex(({ post }) => post === postId);
const userHasLiked = userLikeIndex > -1;
if (userHasLiked) {
setLikeId(userLikeList[userLikeIndex]._id);
console.log('[state] setLikeId changed');
}
console.log('[state] isLiked : ', isLiked);
console.log('[state] likeId : ', likeId);
console.log(
'---------------------------------------- checkUserHasLiked end',
);
return userHasLiked;
};
const countPostLikes = useCallback(async () => {
const postDetailsData = await getPostDetails({ postId });
return postDetailsData.likes.length;
}, [postId]);
/* useEffect */
useEffect(async () => {
console.log('---------------------------------------- useEffect start');
const likeCounts = await countPostLikes();
setLikeCount(likeCounts);
const userHasLiked = await checkUserHasLiked();
console.log('useEffect : userHasLiked?', userHasLiked);
if (userHasLiked) {
setIsLiked(true);
console.log('useEffect : setIsLiked true ? ', isLiked);
} else {
// setIsLiked(false);
// console.log('useEffect : setIsLiked false ?', isLiked);
}
console.log('---------------------------------------- useEffect end');
}, [isLiked]);
/* handleClick */
const handleClick = async () => {
if (isLiked) {
await deleteLike(likeId);
setIsLiked(false);
setLikeId('');
return;
}
const { _id } = await createLike(postId);
setIsLiked(true);
setLikeId(_id);
};
console.log('---------------------------------------- DOM rendered');
return (
<Article>
<Link to={`/post/${postId}`}>
<HiddenHeading level={2}>포스트</HiddenHeading>
<ImageWrapper>
<Image src={image} alt="업로드 이미지" />
</ImageWrapper>
<Paragraph>
{content}
<MoreButton>더보기</MoreButton>
</Paragraph>
<ButtonContainer>
<LikeButton id={postId} onClick={handleClick}>
{isLiked ? <StyledFavoriteIcon /> : <FavoriteBorderOutlinedIcon />}
</LikeButton>
<LikeCounter>{likeCount}</LikeCounter>
<CommentButton>
<CommentOutlinedIcon />
</CommentButton>
<CommentCounter>{comments.length}</CommentCounter>
</ButtonContainer>
</Link>
</Article>
);
};
export default Post;
Post.defaultProps = {
image: '',
content: '',
comments: [],
};
Post.propTypes = {
image: PropTypes.string,
content: PropTypes.string,
comments: PropTypes.array,
};
const Article = styled.article`
background-color: #f5f5f5;
border-radius: 1rem;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.24));
font-size: 0.75rem;
margin: 0.5rem 0;
width: 100%;
`;
const ImageWrapper = styled.div`
background-color: gray;
border-radius: 1rem 1rem 0 0;
height: 20.25rem; /* temp */
overflow: hidden;
position: relative;
width: 100%;
`;
const Image = styled.img`
height: auto;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 100%;
`;
const Paragraph = styled.p`
margin: 0;
padding: 0.75rem;
`;
const MoreButton = styled.button`
background-color: transparent;
border: 0;
color: #c4c4c4;
font-size: 0.75rem;
font-weight: bold;
`;
const ButtonContainer = styled.div`
align-items: center;
display: flex;
padding: 0 0.75rem 0.75rem 0.75rem;
`;
const LikeButton = styled.button`
background-color: transparent;
border: 0;
padding: 0;
`;
const LikeCounter = styled.span`
margin: 0 0.3rem;
`;
const CommentButton = styled.button`
background-color: transparent;
border: 0;
padding: 0;
`;
const CommentCounter = styled.span`
margin: 0 0.3rem;
`;
const StyledFavoriteIcon = styled(FavoriteIcon)`
color: red;
`;