handleLikeButtonClick는 좋아요 버튼을 누르면 동작하는 함수이다.
const handleLikeButtonClick = async () => {
// 로그인 체크
if (!currentUserUid) {
alert('로그인이 필요합니다.');
return;
}
// !좋아요인 경우
if (!like) {
// 데이터 추가
await setDoc(doc(dbService, 'likes', currentUserUid), {
userId: currentUserUid, // user id
docId: recipe.RCP_SEQ, // filed id
RCP_NM: recipe.RCP_NM, // 레시피명
RCP_PAT2: recipe.RCP_PAT2, // 레시피 종류
});
// true로 상태 변경
setLike(true);
console.log('레시피 찜');
} else {
const isLiked = doc(dbService, 'likes', currentUserUid);
// 이미 좋아요가 되어 있는 상태이면 삭제
deleteDoc(isLiked);
// false로 상태 변경
setLike(false);
console.log('레시피 찜 취소');
}
};
const handleLikeButtonClick = useCallback(async () => {
// 로그인 체크
if (!currentUserUid) {
alert('로그인이 필요합니다.');
return;
}
// !좋아요인 경우
if (!like) {
// 데이터 추가
await setDoc(doc(dbService, 'likes', currentUserUid), {
userId: currentUserUid, // user id
docId: recipe.RCP_SEQ, // filed id
RCP_NM: recipe.RCP_NM, // 레시피명
RCP_PAT2: recipe.RCP_PAT2, // 레시피 종류
});
// true로 상태 변경
setLike(true);
console.log('레시피 찜');
} else {
// 이미 좋아요가 되어 있는 상태이면 삭제
const isLiked = doc(dbService, 'likes', currentUserUid);
deleteDoc(isLiked);
// false로 상태 변경
setLike(false);
console.log('레시피 찜 취소');
}
}, [like, currentUserUid, recipe]);
const handleLikeButtonClick = useMemo(() => {
return async () => {
// 로그인 체크
if (!currentUserUid) {
alert('로그인이 필요합니다.');
return;
}
// !좋아요인 경우
if (!like) {
await setDoc(doc(dbService, 'likes', currentUserUid), {
userId: currentUserUid, // user id
docId: recipe.RCP_SEQ, // filed id
RCP_NM: recipe.RCP_NM, // 레시피명
RCP_PAT2: recipe.RCP_PAT2, // 레시피 종류
});
// true로 상태 변경
setLike(true);
console.log('레시피 찜');
} else {
// 이미 좋아요가 되어 있는 상태이면 삭제
const isLiked = doc(dbService, 'likes', currentUserUid);
deleteDoc(isLiked);
// false로 상태 변경
setLike(false);
console.log('레시피 찜 취소');
}
};
}, [like, currentUserUid, recipe]);
useCallback
은 메모이제이션된 함수를 반환
하는 데 사용되며,useMemo
는 메모이제이션된 값을 반환
하는 데 사용됨.useCallback은 종속성 배열 내 값들이 변경될 때마다 새로운 함수를 생성하고 값이 변경되지 않을 때에는 이전에 생성된 함수 반환.
useMemo는 마찬가지로 종속성 배열 내 값들이 변경될 때마다 연산을 실행, 값이 변경되지 않으면 이전에 계산된 값을 반환
함.useCallback과 useMemo는 적용할만한 코드가 없었지만 react.memo를 적용할 컴포넌트를 찾음.
...
const RecipeCard = ({ recipe }: { recipe: Recipe }) => {
const navigate = useNavigate();
const handleCardClick = () => {
navigate(`/detail/${recipe.id}`);
};
return (
<>
<RecipeCardWrapper onClick={handleCardClick}>
<RecipeImgWrapper>
<img src={recipe.image} />
</RecipeImgWrapper>
<RecipeTextWrapper>
<p>{recipe.type}</p>
<h1>{recipe.name}</h1>
</RecipeTextWrapper>
</RecipeCardWrapper>
</>
);
};
export default React.memo(RecipeCard);
...
useMemo
와 useCallback
은 함수의 반환 값
과 함수 자체
를 메모이제이션
하는 데 사용, React.memo
는 함수형 컴포넌트의 렌더링 결과를 메모이제이션
하는 데 사용.앞서 훅을 테스트했던, 레시피 찜 기능을 위해 만든 함수는 데이터 구조가 변경됨에 따라 아래와 같이 코드가 바뀌었다.
// 레시피 찜
const handleLikeButtonClick = () => {
// 로그인 체크
if (!currentUserUid) {
openAlert('로그인이 필요합니다.');
return;
}
// 문서 참조
const userRef = doc(dbService, 'users', currentUserUid);
// 문서 데이터 가져오기
getDoc(userRef)
.then((userDoc) => {
// 문서가 존재하면 기존 데이터에 레시피명 추가 또는 삭제
if (userDoc.exists()) {
const likes = userDoc.data()['user-likes'] || [];
if (!like) {
// 레시피 찜
const updatedLikes = [
...likes,
// 마이페이지 RecipeCard 출력에 필요한 정보들
{
id: recipe.id,
type: recipe.type,
name: recipe.name,
image: recipe.image,
},
];
return updateDoc(userRef, { 'user-likes': updatedLikes });
} else {
// 레시피 찜 취소
const updatedLikes = likes.filter(
(item: any) => item.name !== recipe.name
);
return updateDoc(userRef, { 'user-likes': updatedLikes });
}
} else {
// 문서가 존재하지 않으면 새 문서 생성 후 레시피명 추가
const likes = [
{
id: recipe.id,
type: recipe.type,
name: recipe.name,
image: recipe.image,
},
];
return setDoc(userRef, { 'user-likes': likes });
}
})
.then(() => {
setLike(!like);
openAlert(like ? '찜 목록에서 삭제했어요.' : '레시피 찜 완료!');
})
.catch((error) => {
console.error('레시피 찜에 실패했습니다.', error);
openAlert('레시피 찜에 실패했습니다.');
});
};