최근에 했던 프로젝트에 리액트 쿼리를 활용하려고 했으나 흐지부지 쓰지 못했던게 아쉬워서 다음 프로젝트에서는 제대로 사용하려고 공부하기 위한 리액트 쿼리 정리이다.
Data prefetching은 데이터를 사전에 가져온다는 뜻이다.
즉, 사용자가 렌더링 할 데이터를 미리 서버에서 가져오는 것이다.
또한 사용자가 특정 페이지에 gcTime보다 오래 머물 수 있다.
이럴 경우를 대비해서 추후 사용자가 사용할 법한 모든 데이터에 프리페칭을 사용한다.
만약, 해당 쿼리에 대한 데이터가 이미 캐시에 있고 만료되지 않은 데이터라면 해당 데이터를 다시 페치하지 않는다.
await queryClient.prefetchQuery({ queryKey, queryFn })
prefetchQuery는 단일 객체를 인수로 받는다
queryFn
gcTime
prefetching요청은 useQueryClient의 메서드이다.
useQueryClient훅을 통해 queryClient객체 변수를 정의해서 prefetchQuery메서드를 사용할 수 있다.
다만 실행 할 때 유의해야 한다.
다음 페이지로 전환하는 가운데onClick이벤트를 실행하는건 좋은 생각이 아니다.
상태 업데이트가 비동기 식으로 일어나기 때문에 이미 업데이트가 진행됐는지 알 방법이 없다.
대신 useEffect훅을 활용해서 현재 페이지에서 생기는 변경사항을 활용할 수 있다.
"currentPage", 즉 현재 페이지가 최대로 정해진 페이지(maxPostPage)보다 작다면 다음 페이지의 데이터는 없으므로 분기문으로 처리해준다.
"nextPage"변수는 미리 가져올 페이지를 저장할 변수이다.
useQueryClient를 통해서 선언한 "queryClient"에 prefetchQuery메서드를 호출해서 객체의 속성에 요청을 보낼 키,데이터 페칭을 할 함수를 콜백함수로 넣어준다.
queryClient.prefetchQuery({
queryKey : ["posts", nextPage],
queryFn : () => fetchPosts(nextPage),
})
위 로직을 통해서 데이터를 프리페치 해오고 해당 데이터는 [ "posts", nextPage ] 키에 저장된다.
작성 한 코드를 실행해보면 1페이지에서 2페이지에 대한 데이터를 프리페치 하고 "Next Page"버튼을 눌러서 다음페이지로 가면 해당 페이지의 다음 페이지가 프리페치 되어서 데이터를 캐시에 저장하는걸 확인 할 수 있다.
만약 다음 페이지를 미리 받아오지 않고 onClick이벤트 핸들러를 실행하면서 해당 페이지에 대한 정보를 가져온다면 API요청을 기다려야 해서 빈 화면을 보거나 로딩 인디케이터를 기다려야 하는데 사용자 경험에서는 매끄럽지 않은 페이지 전환이 된다.
왜 동일키로 데이터를 받아오지 않고 키에 대한 의존성배열을 추가해서 데이터를 받아올까?
처음에 "prefetchQuery를 동일한 키를 사용해서 업데이트 하면 안될까?"는 생각으로 동일한 키로 Pagination을 구현하려고 했는데 이렇게 한다면 동일한 쿼리키를 사용함에 따라 해당 캐시 데이터를 새로운 API요청을 통해서 받아와야 하는 문제가 생겨서 페이지 전환간에 매끄럽지 못하다는 문제가 발생했다.
이에대한 해결책으로는 매 Page 마다 새로운 키를 갖는 것이다.
매 Page마다 새로운 키를 줘서 새롭게 페치 시켜야 하는 것이다.
즉, 데이터가 변경될 경우 키도 변경되도록 하면 매 Page마다 새로운 키에 데이터를 저장할것이고 매 Page마다 데이터가 따로따로 있다는건 페이지 전환간에도 해당 데이터만 캐시에서 불러오면 되므로 페이지 전환이 매우 매끄러워졌다.