2월 27일 여정50일차이다.
const { data } = useQuery(["showDetail", id], () =>
showDetailStore({ id, token })
);
const dlelteStoreItem = useMutation(deleteStore, {
onSuccess: () => {
navigate("/");
},
});
어떤 아이템을 삭제하고 문제가 발생하였다. 이유는 리엑트 쿼리에서 아이템을 삭제하기 전에 showDetail로 한번 불러오고, 삭제한 이후에 refetch 되면서 한번더 불러와지는 문제였다.
당연히 삭제된 아이템이니까 불러와도 아무 데이터가 없는 것이 당연하다.
신기한것은 같이 프로잭트를 진행하던 분의 컴퓨터에서는 에러가 나타나지 않았다.
일단 코드를 여러번 살펴보았다. showDetail라는 키 값을 다른 곳에서 쓴 적이 있는지, 또는 dlelteStoreItem을 다른 곳에서 쓴적이 있는지 보았다. 그러나 Detail.jsx에서 밖에 쓰이지 않았다. ajax도 살펴보았지만 2번 보내질만한 원인이 없었다. 혹여나 id랑 token이 변해서 한번더 ajax 호출이 일어나는 건가 싶었다. 그래서 useEffect와 refetch를 사용하여 id랑 token값이 변할 때만 reftech가 되도록 해보았지만 소용없었다.
일단 리액트 쿼리에서 refetch가 되는 조건들을 살펴보자.
1. 새로운 query instance가 마운트 될 때 ( page를 이동 했다가 왔을 때 의미)
2. 브라우저 화면을 이탈 했다가 다시 focus 할 때
3. 네트워크가 다시 연결될 때
4. 특별히 설정한 refetch interval에 의한 경우 (refetchInterval)
이렇게 4가지의 경우가 있다. 물론 나는 여기 4가지 중에 해당되는 경우가 없었다. 그렇지만 이번 문제의 근본은 refetch였다.
그래서 refetch를 막을 방법을 찾았다.
찾아보니 staleTime이라는 것을 발견하게 되었다. 밑에와 같이 설정을 해주었다.
const { data } = useQuery(
["showDetail", id],
() => showDetailStore({ id, token }),
{ staleTime: 1000 * 50 }
);
기본적으로 서버에서 전달받은 데이터는 리액트 쿼리의 자료구조 내용 중에 cahe에 저장이 된다. 이떄 이 캐시 데이터의 "신선한 상태"가 언제까지 되는지에 대한 옵션을 설정해 준 것이다.
리액트 쿼리는 데이터를 받아오는 즉시 stale하다고 판단하며 캐싱 데이터와 무관하게 fetching을 수행한다.
여기서 중요한 것은 바로 stale 상태이다. useQuery는 호출할 당시에 옵션으로 staletime을 따로 지정해주지 않았었다면, 항상 캐싱되어 있는 데이터는 stale하다고 여기기 때문에 refetching을 하게 되어 서버에 계속적인 요청을 하게된다.
따라서 삭제버튼을 누른 후에도 한번더 fetching이 일어나는 것이다. 그래서 위와 같이 staleTime을 설정해주었다.
그 결과 콘솔에 에러가 안뜨는 정말 눈물나는 트러블슈팅을 하게 되었다.
여기서 주의 해야할 점이 있다. 만약 데이터 구조가 자주자주 변하는 어플리케이션이라면 지정하지 않는 편이 좋고 해당 브라우저에 표현되는 내용의 데이터들이 정적이라면 staletime을 지정해주고 요청하는 것이 서버의 부담을 경감시킬 수 있다.
https://2ham-s.tistory.com/407
이것때문에 하루종일 삽질을 하였다. 그렇지만 해결이 되어서 너무 좋다.