반응형
이전 글
React Query를 처음 쓰는데 생각보다 옵션들이 너무 많아서 제대로 활용하지 못하는 것 같았다.
그리고 내가 짰던 좋아요 로직에 대한 의심이 계속 들었던 와중에 좋아요가 적용이 안되는 오류가 발생했다.
그래서 하루종일 좋아요만 붙들고 수정했다.
커밋 링크
이전 코드와 달라진 점 (코드는 아래쪽에)
1. useMutation에 onSettled 함수를 추가해서 데이터 업데이트가 성공하든 말든 invalidate를 수행하게 함
=> 이 부분은 나중에 확인해보니 꼭 필요하진 않은 부분이어서 삭제했다.
2. mutate를 useEffect 안에 배치해서 isLike가 변할때마다 업데이트 되도록 했는데, 이를 deps를 삭제하고 useEffect, return을 사용해서 컴포넌트가 언마운트 될 때만 업데이트 되도록 쓰로틀링을 적용해 서버 요청을 더 줄일 수 있도록 구현했다.
=> 이 부분도 나중에 확인해보니 좋아요 누른 후 새로고침을 수행하면 좋아요가 적용되지 않아서 실시간 업데이틀 변경했다..
3. 가장 중요한 것은 76~82번째 줄의 useEffect였다.
이 두개는 useQuery로 요청한 데이터가 조금씩 늦게 불러질 때 데이터 일관성이 떨어지기 때문에 추가했다.
그래서 이 둘 중 하나라도 삭제되면 좋아요 수, 하트 유지 여부가 일관성이 떨어지기 때문에 꼭 필요했다.
수정된 코드
import styled from '@emotion/styled';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { AiOutlineHeart, AiFillHeart } from 'react-icons/ai';
import { updateLike, updateMyProject } from '../../apis/postDetail'; //여기서 에러 발생 :모듈 또는 해당 형식 선언을 찾을 수 없습니다.
import { findWithCollectionName } from 'apis/findWithCollectionName';
import { useAuth, useGlobalModal } from 'hooks';
import COLORS from 'assets/styles/colors';
const Likes = ({ pid, version = 'web' }: any) => {
const { uid } = useAuth();
const { openModal } = useGlobalModal();
const handleLikeButton = async (event: any) => {
event.preventDefault();
if (isLike) {
setIsLike(false);
setCountLike(countLike - 1);
} else {
setIsLike(true);
setCountLike(countLike + 1);
}
};
//좋아요한 프로젝트 조회
const { data: myProjects } = useQuery({
queryKey: ['myProjects', uid],
queryFn: () => findWithCollectionName('myprojects', uid),
});
const { data: projectLike } = useQuery({
queryKey: ['post', pid],
queryFn: () => findWithCollectionName('post', pid),
});
const [countLike, setCountLike] = useState(projectLike?.like);
const [isLike, setIsLike] = useState(myProjects?.likedProjects.includes(pid));
const queryClient = useQueryClient();
const { mutate: updateLikeMutate } = useMutation(
() => updateLike(pid, countLike),
{
onSettled: () => {
queryClient.invalidateQueries(['post', pid]);
},
onSuccess: () => {
queryClient.invalidateQueries(['post', pid]);
setCountLike(projectLike?.like);
},
},
);
const { mutate: updateMyProjectMutate } = useMutation(
() => updateMyProject(uid, pid, isLike),
{
onSettled: () => {
queryClient.invalidateQueries(['myProjects', uid]);
},
onSuccess: () => {
queryClient.invalidateQueries(['myProjects', uid]);
},
},
);
useEffect(() => {
setCountLike(projectLike?.like);
return () => {
updateMyProjectMutate();
updateLikeMutate();
setIsLike(myProjects?.likedProjects.includes(pid));
};
}, []);
useEffect(() => {
setCountLike(projectLike?.like);
}, [projectLike?.like]);
useEffect(() => {
setIsLike(myProjects?.likedProjects.includes(pid));
}, [myProjects?.likedProjects]);
return (
<IconButton
onClick={(event) => {
if (!uid) {
openModal('login', 0);
return;
}
handleLikeButton(event);
}}
>
{isLike ? (
<FillHeart version={version} />
) : (
<LineHeart version={version} />
)}
관심 {countLike ?? ' 0'}
</IconButton> // 로그아웃인 경우 관심 버튼 클릭 시 likedProjects에 데이터가 없어서 로직 에러 발생: 예외처리 필요
);
};
export default Likes;
const IconButton = styled.button`
display: flex;
align-items: center;
gap: 0.5rem;
`;
const FillHeart = styled(AiFillHeart)<{ version: string }>`
font-size: ${(props) => (props.version === 'mobile' ? '1rem' : '1.5rem')};
color: ${COLORS.pink};
`;
const LineHeart = styled(AiOutlineHeart)`
font-size: ${(props: { version: string }) =>
props.version === 'mobile' ? '1rem' : '1.5rem'};
color: ${COLORS.gray750};
`;
반응형
'매일 해내는 개발 > Develog' 카테고리의 다른 글
[Develog] D-day와 옵저버 (1) | 2023.03.09 |
---|---|
[Develog] yarn berry (0) | 2023.03.06 |
[Develog] 좋아요 기능 구현(with firebase, useQuery, useMutation) (0) | 2023.02.25 |
[Develog] VS Code 꿀팁! 단축키 정리 (0) | 2023.02.11 |
[Develog] Craco란? Craco 설치 방법 (0) | 2023.02.08 |
댓글