도움돼요 기능을 구현한 뒤 도움돼요 횟수를 카운트하여 표시해주는 것이 필요하다고 생각이 되었다.
도움돼요 기능은 supabase reviews table의 likes column에 사용자 아이디를 뒤에 추가하는 방식으로 구현하였다.
나는 reviews 데이터들을 useQuery를 사용하여 상위컴포넌트에서 불러왔고 이를 ReviewCard.tsx에서 props로 받은 상태였다.
또한 도움돼요 기능을 useMutation을 활용하여 추가하고 삭제할 수 있도록 구현하였다.
따라 reviews 데이터들이 바뀔 때마다 queryKey:["reviews"]
데이터가 무효화되고 캐싱되기 때문에 useState나 useEffect를 사용하지 않아도 실시간으로 데이터의 변화를 알 수 있었다.
도움돼요 숫자를 셀 수 있도록 상위 컴포넌트에서 로직 작성
const getLikeCount = (likes: string | string[] | null | undefined) => {
// likes가 null, undefined, 빈 배열인 경우 0 반환
if (!likes || (Array.isArray(likes) && likes.length === 0)) {
return 0;
}
// likes가 문자열일 경우 쉼표로 분리하고 빈 문자열 필터링
if (typeof likes === 'string') {
const splitLikes = likes.split(',').filter((like) => like.trim() !== '');
return splitLikes.length;
}
// likes가 배열인 경우 길이 반환
const likesLength = Array.isArray(likes) ? likes.length : 0;
return likesLength >= 1000 ? '999+' : likesLength;
};
reviews.map 내에서 getLikeCount를 불러와 review데이터 전달 & props로 ReviewItem.tsx에 카운트 정보 전달
return (
<div>
{reviews.map((review) => {
const user = users?.users.find((u: User) => u.id === review.user_id);
if (!user)
return (
<div
className='text-center text-[14px] text-gray-300'
key={review.id}
>
사용자를 찾을 수 없습니다.
</div>
);
const isLiked = review.likes?.includes(signedUserId) ?? false;
const likeCount = getLikeCount(review.likes);
return (
<ReviewItem
key={review.id}
review={review}
user={user}
isExpanded={expandedReview === review.id}
onToggle={() => toggleContent(review.id)}
onNavigate={() => handleReviewDetail(review.id)}
isLiked={isLiked}
onLikeToggle={() => handleLikeToggle(review)}
likeCount={likeCount}
/>
);
})}
</div>
ReviewItem.tsx에서 props로 받아온 count횟수 도움돼요에 함께 표시
const ReviewItem = ({
review,
user,
isExpanded,
onToggle,
onNavigate,
onLikeToggle,
isLiked,
likeCount,
}: {
review: Review;
user: User;
isExpanded: boolean;
onToggle: () => void;
onNavigate: () => void;
onLikeToggle: () => void;
isLiked: boolean;
likeCount: number | string;
return (
~~~
~~~
<span className={`${isLiked ? 'text-white' : ''}`}>도움돼요({likeCount})</span>
</button>
</>
)}
</div>
)
🔥 문제점
: 데이터가 빈 배열인데도 도움돼요가 1개가 있다고 뜨는 현상
☘️ 해결방법
: supabase에서 데이터가 도움돼요를 눌렀다가 삭제하였을 때
likes column : '[]' 로 들어오는 것을 발견하였고 이것이 length로 체크가 되었다.
likes 데이터가 '[]'일 때 0을 반환하도록 조건 추가
if (likes === '[]') return 0;
const getLikeCount = (likes: string | string[] | null | undefined) => {
// likes가 null, undefined, 빈 배열인 경우 0 반환
if (!likes || (Array.isArray(likes) && likes.length === 0)) {
return 0;
}
if (likes === '[]') return 0; // 추가
// likes가 문자열일 경우 쉼표로 분리하고 빈 문자열 필터링
if (typeof likes === 'string') {
const splitLikes = likes.split(',').filter((like) => like.trim() !== '');
return splitLikes.length;
}
// likes가 배열인 경우 길이 반환
const likesLength = Array.isArray(likes) ? likes.length : 0;
return likesLength >= 1000 ? '999+' : likesLength;
};
해결완료