좋아요를 안 한 상태라면 좋아요, 좋아요를 한 상태라면 좋아요 취소 구현하기
const [likes, setLikes] = useState(item.likes);
const [liked, setLiked] = useState(item.liked);
const changeLikes = () => {
if (!item.liked) {
setLikes((prev) => prev + 1);
setLiked(true);
}
if (item.liked && item.likes > 0) {
setLikes((prev) => prev - 1);
setLiked(false);
}
};
const onChangeLikes = async () => {
try {
changeLikes();
await calculate({ id: item.id, likes, liked });
} catch (error) {
console.log("error", error);
}
};
- DB에
likes
(좋아요수),liked
(좋아요 여부) 추가useState
로likes
,liked
관리- 하트를 클릭할 때마다
setLikes
,setLiked
실행
liked
가false
라면setLikes((prev) => prev + 1)
liked
가true
라면setLikes((prev) => prev - 1);
버그
좋아요가 1씩 증가하거나 감소하지 않고 2씩 동작
onChageLikes
가 실행되면 setLikes
는 매번 실행되지만 setLiked
는 두 번째에만 실행이 되기 때문인데, 서버와 통신하게 되면서 setState
의 순서를 보장하지 못하게 되었기에 해당 버그가 발생했다.
튜터님께 조언을 구해보니 이 부분은 내가 코드를 잘못 짠 게 아니고 원래 useState
라는 놈이 그렇다고 한다.. 그래서 프로젝트의 규모가 커질수록 useState
로 관리하는 일이 잘 없다고 한다.
const likesArray = item.userLikes;
const countLikes = () => {
if (!likesArray.includes(item.userId)) {
likesArray.push(item.userId);
} else if (likesArray.includes(item.userId)) {
const idx = likesArray.indexOf(item.userId);
likesArray.splice(idx, 1);
}
};
- DB에
userLikes
배열 생성- 좋아요 실행시
userLikes
에 현재userId
추가- 좋아요 취소시
userLikes
에서 해당userId
와 일치하는 값 제거- 좋아요수는
userLikes
길이로 반환
이런 로직으로 구현하니까 버그도 없고 코드도 훨씬 깔끔해졌다! 물론 이것도 배열에서 특정 요소 제거하는 부분에서 또 한참 헤맸다 ㅎ... 알고리즘 한창 풀었을 땐 비슷한 문제 뚝딱 풀었었는데 한동안 안하다 보니 또 기억이 나질 않는다.... 자바스크립트의 중요성을 또 한 번 느꼈다.