📝 치열한 고민의 흔적... 좋아요가 이렇게 어려운 것일 줄이야
📝 아직 수정이 필요한 부분 : 현재 로그인한 유저 email 확인하는 방식
기존
: email이 필요한 api에서 await supabase.auth로 email을 매번 가져옴변경
: zustand에 저장해놓은 current user Info 를 가지고 인자로 email을 넘겨주는 방식으로 변경하기
(zustand로 관리하는 전역상태는 화면 렌더링시 useQuery보다 늦게 값을 가져오기 때문에, useQuery에서 enabled 옵션 추가 및 isPending을 사용하자)
🤍 (참고)isLoading
과isPending
의 차이 : isLoading은 query가 실행중인 상태를 확인해주는 것, isPending은 query가 실행되기 전의 상태를 확인해주는 것
-> enabled 옵션을 추가해놨으면 query가 실행되기 전의 상태를 확인해주는 로직이 필요하기 때문에 isLoading이 아닌 isPending을 사용해주어야 한다!
🧡 좋아요 로직 정리 🧡
// 컴포넌트
const [isLike, setIsLike] = useState(false);
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
// 화면 렌더링시 - 로그인 상태일때만 이미 좋아요한 그림인지 미리 확인하기
useEffect(() => {
if (isLoggedIn) {
const fetchData = async () => {
try {
const response = await isCheckLikeState(id);
setIsLike(response);
} catch (error) {
console.error(error);
}
};
fetchData();
} else if (!isLoggedIn) {
setIsLike(false);
}
}, [id, isLoggedIn]);
// api
// 유저가 좋아요 했는지 미리 확인하기 - likes에서 email, drawing_id 존재하는지 확인
export const isCheckLikeState = async (drawingId: number) => {
// current loggedIn user의 email 가져오기
const { data: user, error: userError } = await supabase.auth.getUser();
if (userError) {
throw userError;
}
const email = user.user.email;
// likes테이블에서 email, drawingId 모두 일치하는값 있는지 확인하기
const { data: like, error } = await supabase
.from("likes")
.select()
.eq("user_email", email)
.eq("drawing_id", drawingId);
if (error) {
throw error;
}
return like.length > 0;
};
// 좋아요 개수 가져오기 api
export const countLikesNumber = async (id: number) => {
const { data, error } = await supabase
.from("likes")
.select()
.eq("drawing_id", id);
if (error) {
throw error;
}
return data.length;
};
'좋아요'인 경우
'좋아요 취소'인 경우
// 컴포넌트
const [isLike, setIsLike] = useState(false);
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
const setIsLoginOpen = useAuthStore((state) => state.setIsLoginOpen);
const queryClient = useQueryClient();
// 현재 그림의 url
const drawingUrl = post.drawing_url;
const { mutate: insertLikeMutation } = useMutation({
mutationFn: ({ id, drawingUrl }: { id: number; drawingUrl: string }) =>
insertLike(id, drawingUrl),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["countLikesNumber"],
});
},
});
// 좋아요 클릭시
// - 좋아요 : likes 테이블에 email, id, url 추가, 하트색 변경
// - 좋아요 취소 : likes 테이블에서 email, id가 같은 열 삭제, 하트색 변경
const handleLikeOnClick = async () => {
if (!isLike) {
if (isLoggedIn) {
insertLikeMutation({ id, drawingUrl });
setIsLike((prev) => !prev);
} else if (!isLoggedIn) {
alert("로그인이 필요한 기능입니다.");
setIsLoginOpen(true);
}
} else if (isLike) {
deleteLikeMutation(id);
setIsLike((prev) => !prev);
}
};
// api
// 좋아요! - likes테이블에 email, id, url 추가하기
export const insertLike = async (id: number, url: string) => {
// current loggedIn user의 email 가져오기
const { data: user, error: userError } = await supabase.auth.getUser();
if (userError) {
throw userError;
}
const email = user.user.email;
// likes 테이블에 insert
const { data, error } = await supabase.from("likes").insert([
{
user_email: email,
drawing_id: id,
drawing_url: url,
},
]);
if (error) {
throw error;
}
return data;
};
// 좋아요 취소 - likes 테이블에서 그림id가 같은 열 삭제
export const deleteLike = async (id: number) => {
// current loggedIn user의 email 가져오기
const { data: user, error: userError } = await supabase.auth.getUser();
if (userError) {
throw userError;
}
const email = user.user.email;
// likes테이블에서 email, id 같은 열 삭제
const { data, error } = await supabase
.from("likes")
.delete()
.eq("drawing_id", id)
.eq("user_email", email)
.select();
if (error) {
throw error;
}
return data;
};