궁금한 점: content로 감싸져있어서 변화를 감지 못해서 refetch가 안되는 걸까요? ⇒ 되는 게 있고 안되는 게 있어요 🙄
기본적인 Flow는,
좋아요 버튼 클릭
→ post 요청(mutation)으로 서버 상태 변경
→ 요청이 성공하면
→ 비동기적으로 query 함수 refetch
→ 실시간 반영
하지만 실패…
// 좋아요 버튼 클릭시 mutation 함수 실행
<div
className="flex items-center gap-2"
onClick={async (e) => {
e.stopPropagation();
likeMutate();
}}
>
// Mutation 함수가 Success 되는 시점에서 Refetch
export function useCommunityLikeMutation(postId: number) {
const { refetch: allListRefetch } = useCommunityPostQuery();
return useMutation(() => postCommunityLikeAxios(accessToken, postId), {
onError: (err) => {
console.log(err);
},
onSuccess: async () => {
await allListRefetch();
console.log('좋아요 상태 변경 반영됨');
},
});
}
⇒ 정상적으로 onSuccess 시점에 리패칭이 일어나고있음을 확인

⇒ 좋아요 상태가 정상 반영되고, onSuccess에 console도 찍혔지만, 어째서인지 빈 배열만 반환됨.

⇒ 혹시 query 함수가 같은 키값을 가지고 리패칭을 시도해서, 데이터가 변경되지 않았다고 판단해서 캐싱된 데이터를 사용하기 때문에 빈 배열을 반환하는건가 해서,
query 함수에 unique한 키값을 넘겨 주고 다시 시도
// Mutation 함수가 success될 때, refetchNew에 유니크한 키값을 주고, 리패치
onSuccess: async () => {
refetchNew = `like${Date.now()}`;
await allListRefetch();
console.log('게시글이 등록되었습니다.');
},
// 쿼리함수에 refetchNew 를 키값으로 줌
let refetchNew = '';
export function useCommunityPostQuery(word?: string, sort?: SortType, order?: OrderType, size?: number, postType?: postType | 'ALL') {
return useInfiniteQuery(['Community',**refetchNew,** word, sort, order, postType], ({ pageParam = 0 }) => getCommunityPostAxios(accessToken, word, sort, order, pageParam, size, postType), {
getNextPageParam: (prevData, allPages) => {
const lastPage = prevData.last;
const nextPage = allPages.length + 1;
return lastPage ? undefined : nextPage;
},
staleTime: 30000,
});
}
⇒ 여전히 빈 배열만이 반환됨.
⇒ 이 방법이 여전히 왜 안되는지 모르겠습니다…
mutation의 onSuccess 내에서 해결할 수 있는 방법이 없다고 판단했고, mutation 함수가 실행되는(좋아요 버튼 onClick)시점으로 돌아왔다.
도저히 왜 refetch가 되지 않는지 이해가 되지 않아서 일단 임시 방편을 마련함..
const [count, setCount] = useState(false);
<div
className="flex items-center gap-2"
onClick={async (e) => {
e.stopPropagation();
likeMutate();
setCount(!count)
>
{count ? likeCount + 1 : likeCount}
</div>
onClick시 변경되는 상태를 서버데이터와 상관없이 useState에 boolean 값으로 반영해주고, 그 값에 따라 likeCount를 적용해줌.
유저가 해당 페이지를 사용하며 변경하는 데이터는 프론트 단에서 관리하고, 페이지를 이동했다가 다시 onMount되는 시점에 서버 상태를 반영해주는 방법을 생각했다.
일단 이건 동작 잘함.
일단 여기서도 isSuccess 를 기준으로 refetch 시도
<div
className="flex items-center gap-2"
onClick={async (e) => {
e.stopPropagation();
likeMutate();
console.log(isSuccess);
if (refetch && isSuccess) {
refetch();
}
}}
>
{likeCount}
</div>


문제1. 한발 늦게 반영이 된다.
⇒ 첫 클릭시에는 리패치가 반응이 없다가, 두번쨰 클릭했을 때, 첫 클릭했을때의 결과가 반영된다…
⇒ mutation 함수와 refetch가 동시에 실행됨
⇒ 즉, 콘솔에는 좋아요가 해제가 되었다고 찍히는데, likeCount는 +1 된다.

문제2. 콘솔에 찍는 isSuccess가 처음 시도부터 성공했음에도 불구하고, 첫시도에 무조건 false를 반환한다.
⇒ 하긴… 콘솔을 비동기로 찍는것도 아니고… 온클릭하자마자 mutation 함수가 성공해서 true값이 되진 않을테니, 어찌보면 당연한 결과.
⇒ 따라서 첫 클릭시에는 refetch가 일어나지 않고, mutation 함수만 실행되어, 서버에만 반영된 것.
⇒ 어쨋든 첫 시도에서 isSuccess 값이 true로 초기화되었으니, 두번째 시도에는 onClick 하자마자 isSuccess의 true 값이 반영되서, refetch와 mutation가 동시에 동작되기 때문에, mutation의 결과가 화면에 보여지는 것이 아닌, 이전의 결과값이 화면에 한발 늦게 보여지는 것.
⇒ 어쨋든, 이제 refetch시 데이터가 잘 들어오고 있다는건 좋은 징조다!!!
React query의 Mutation 함수는 promise를 반환하지 않기 때문에, async await이나 then 함수를 사용할 수 없다. 따라서 setTimeout 을 통해 강제로 비동기로 동작하도록 처리하도록 해봤다.
<div
className="flex items-center gap-2"
onClick={async (e) => {
e.stopPropagation();
likeMutate();
if (refetch) {
setTimeout(() => {
refetch();
}, 200);
}
}}
>
{likeCount}
</div>

200ms 정도 시간텀을 두니, 적절히 잘 비동기적으로 데이터 Refetch가 실행되고, likeCount 역시 잘 변경된다!!!
⇒ 하지만 역시 불완전한 임시방편에 불과하다. 그 이유는,
Mutation 함수가 useState 상태를 업데이트하는 경우, useEffect를 사용해서 isSuccess 상태가 업데이트된 후, Refetch 하기. (성공!!!!!🔥)
const [likeSuccess, setLikeSuccess] = useState(false);
const handleLike = () => {
likeMutate();
setLikeSuccess(true);
};
useEffect(() => {
if (likeSuccess) {
console.log(isSuccess);
if (refetch && isSuccess) {
refetch();
}
}
}, [likeSuccess, refetch, isSuccess]);
return (
<div
className="flex items-center gap-2"
onClick={async (e) => {
e.stopPropagation();
handleLike();
}}
>
{likeCount}
</div>
)