Redux를 공부하다가 React-Query에 대해 알게 되었다. React Query의 속성에 isLoading이 있는 것을 알게 되었고, 코드를 훨씬 간결화할 수 있어 프로젝트에 도입하게 되었다.
정확하게 React Query를 이해하지 못하고 사용하다 보니 예상치 못한 이슈들이 발생했다.
다른 탭 이동 후 다시 돌아 왔을 때, 다시 api 호출하는 것을 발견했다. api 호출이 필요없는 시점이기에 네트워크 비용을 아끼기 위해서 원인을 파악하고자 하였다.
그러다가 React Query를 자세히 공부하게 되었고, 그 내용을 지금 정리하려 한다.
const { isLoading, isError, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
queryKey는 unique 해야 한다. 배열도 가능하다
해당 키는 refetching, caching, 그리고 query를 공유할 때 쓰인다.
queryFn에 쓰이는 변수가 있다면 정의를 해주어야 한다.
function Todos({ todoId }) {
const result = useQuery({
queryKey: ['todos', todoId],
queryFn: () => fetchTodoById(todoId),
})
}
api를 fetch하는 코드를 여기에 작성하면 된다.
useQuery가 제공하는 속성이다. 이것이 너무 유용해서 나는 사용하게 되었다.
옵션은 굉장히 많다. (사실 위의 속성도 저것보다 훨씬 많다.) 더 많은 내용은 공식문서를 참고하면 될 것 같고, 지금은 내가 잘 사용하는 or 사용할 것 같은 옵션들을 정리해보려한다.
이해하기 어려웠는데 한 블로그를 보고 이해가 쉽게 되었다! (참고에 걸어둠)
모든 컴포넌트가 마운트 해제되는 시점에서 비활성 상태로 전환되고 캐싱한다는 의미이다. 즉 쿼리를 사용하는 모든 컴포넌트가 현재 화면에 없다면 그 쿼리는 비활성 상태가 된다. 그 비활성 상태가 되고 난 이후 얼마 동안 데이터를 캐싱하고 있느냐이다.
cacheTime의 default 값은 5분이다.
지금은 gcTime으로 변경되었다. 가비지 콜렉터와 비슷한 느낌이라서!
윈도우에 다시 포커스되었을 때나, 컴포넌트가 다시 마운트될 때나, 네트워크가 재연결되었을 때 등의 트리거가 발생했을 때 다시 페치한다.
staleTime의 default 값은 0이다. 즉, 위와 같은 트리거가 발생하였을 때 항상 다시 페치하지만, staleTime을 조정해주면 그 시간동안은 다시 페치하지 않는다.
사용자가 현재 화면에서 포커스를 잃었다가 다시 돌아오면 fetch를 한다. 이 것 때문에 탭 전환시 지속적인 네트워크 요청이 발생한 것이었다.
default 값은 true이다.
+refetchOnMount, refetchOnReconnect 도 이름에서 알 수 있듯이 마운트 할때마다, 네트워크가 재연결 될때마다 fetch한다. 즉, windowFocus, Mount, Reconnect가 stale 상태인 것!
true일 경우 useEffect 내의 fetch처럼 매번 렌더링시에 실행된다. 만약, useQuery를 이벤트 발생 시에 쓰고 싶다면 enabled를 false로 설정하고, refetch 속성을 사용하여 useQuery를 실행시킬 수 있다. 이번에 공부하며 알게 되었는데 api를 가독성있게 정리하는데 유용하게 잘 사용될 것 같다.
const { data, refetch } = useQuery('search', getSearch,
{
enabled: false
}
);
아니면 id가 있을 경우에만 실행시킬 수도 있다.
const {
status,
fetchStatus,
data: projects,
} = useQuery({
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
// The query will not execute until the userId exists
enabled: !!userId,
})
default 값은 false이다.
fetch에 성공 혹은 실패시에 실행할 코드를 작성할 수 있다.
{
onError: (error) => {
console.error('논문 정보를 불러오는 데 실패하였습니다:', error)
Sentry.captureException(error)
}
}
데이터를 fetch하기 전에 표시할 데이터에 대한 초기값을 설정해줄 수 있다.
useQuery는 get 요청을 할 때 쓰인다. post/put/dele는 useMutation을 사용하면 된다!
내가 실제 쓰고 있는 코드를 발췌해왔다.
const { mutate } = useMutation(
(payload: paperLikePayload)=> postApi(api, `/api/paperlikeonoff`, payload)
.then(async response => {
if (response.status === 401) {
await refreshApi(api, notify, navigate)
} else if (response.status === 400) {
navigate(`/home`)
}
})
.finally(()=>{
setOpen(false)
setPaperIdArray(prevArray => [...prevArray, payload.paperId])
}), {
onError: (error) => {
console.log("관심 논문 삭제에 실패하였습니다", error)
Sentry.captureException(error)
}
}
)
https://tanstack.com/query/v4/docs/react/overview