TIL : 최종프로젝트 10일차

hihyeon_cho·2023년 2월 19일
0

TIL

목록 보기
73/101

오늘은 좋아요 기능을 구현했다.

좋아요 기능 구현하기

  1. 좋아요 여부와 좋아요 수를 저장하도록 useState로 state를 만들고, firestore에서 받아온 좋아요 수를 likeCount에 넣기 위해 변수로 지정했다.
interface LikeProps {
  paramId: string | any;
  course: CourseType | undefined;
}

const LikeBtn = ({ paramId, course }: LikeProps) => {
  
  const [like, setLike] = useState(false);
  const courseLikes = course && course?.likes;
  const [likeCount, setLikeCount] = useState<number | any>(0);
  1. 좋아요 버튼을 눌렀을 때, 버튼이 토글되고 likeCount의 내용이 변경되는 코드를 작성한다.
  const submitLike = async () => {
    if (!authService.currentUser) {
      setLike(false);
      alert("좋아요는 로그인 후 이용가능합니다.");
      return;
    }
    if (like === true) {
      setLike(false);
      setLikeCount(likeCount - 1);
    } else if (like === false) {
      setLike(true);
      setLikeCount(likeCount + 1);
    }
  };
  1. firestore에서 좋아요 수가 변경되거나, 현재 사용하고 있는 사용자가 변화할때마다 likeCount state에 현재 firestore에 저장된 좋아요 수를 업데이트하고, 좋아요 한 사용자라면 좋아요를 했다는 표시를 해주도록 작성했다.
useEffect(() => {
    setLikeCount(courseLikes);
    const likeUser = course?.likesID.find((user) => user === currentId);
    if (likeUser) {
      setLike(true);
    } else {
      setLike(false);
    }
  }, [courseLikes, authService.currentUser]);
  1. firestore에 좋아요 수와, 좋아요 한 user의 id를 추가하여 업데이트하는 코드를 작성했다.

☄️ Trouble Shooting

하지만, 여기서 오류가 하나 있었는데,

좋아요 버튼을 눌렀을 때, firestore안에서 좋아요 수만 바로 업데이트 되지 않고, 버튼을 다시 눌러야지만 반영이 되는 오류가 발생했다.

기존에 잘못 작성한 코드

const [like, setLike] = useState(false);
const [likeCount, setLikeCount] = useState<number | any>(0);

const submitLike = async () => {
    if (!authService.currentUser) {
      setLike(false);
      alert("좋아요는 로그인 후 이용가능합니다.");
      return;
    }
    if (like === true) {
      setLike(false);
      setLikeCount(likeCount - 1);
		  await updateDoc(courseRef, {
          likes: likeCount,
          likesID: arrayRemove(currentId),
        });
    } else if (like === false) {
      setLike(true);
      setLikeCount(likeCount + 1);
		  await updateDoc(courseRef, {
          likes: likeCount,
          likesID: arrayUnion(currentId),
        });
    }
  };

이 문제는 state가 새롭게 렌더링 될 때 바뀌는데, lifecycle 기준으로 redering이 아직 일어나지 않아 likeCount 값이 변화되지 않은 상태로 updateDoc이 실행되었기 때문이었다.

그러므로, like, likeCount 가 변화되었을 때, 리렌더링하여 바뀐 likeCount값이 업데이트 될 수 있도록,
아래와 같이 useEffect 안에 updateDoc 로직을 넣음으로써 해결할 수 있었다.

해결 한 코드

import { arrayRemove, arrayUnion, doc, updateDoc } from "firebase/firestore";
import { authService, dbService } from "../../utils/firebase";

const courseRef = doc(dbService, "courses", paramId);
const currentId = authService.currentUser?.uid;

useEffect(() => {
    const updateLikes = async () => {
      if (like) {
        await updateDoc(courseRef, {
          likes: likeCount,
          likesID: arrayUnion(currentId),
        });
      } else {
        await updateDoc(courseRef, {
          likes: likeCount,
          likesID: arrayRemove(currentId),
        });
      }
    };
    updateLikes();
  }, [like, likeCount]);

튜터님의 피드백으로 위와 같이 수정했더니, 좋아요 수가 firestore에 바로바로 반영이 되어 해결할 수 있었다.

배운 내용

⭐ 컴포넌트는 return하는 부분에서 렌더링 된다. useEffect에서 의존성 배열에 값을 넣으면 렌더링 되는 부분에서 의존성배열 안의 값이 바뀔 때 다시 렌더링이 되는데, 의존성 배열 안의 값이 이전값과 비교해서 바뀌었다면 바뀐 값을 기준으로 실행된다.

profile
코딩은 짜릿해 늘 새로워 ✨

0개의 댓글