어제까지 리액트쿼리를 사용하지 않고 더보기 기능을 구현했었다. 리액트쿼리를 사용할 거면 조회할 때 써보시라고 권해주셔서 코드를 수정하기로 하였다.
const useLoadMore = (fetchFunction) => {
const [currentPage, setCurrentPage] = useState(1);
const [data, setData] = useState(null);
const [totalPage, setTotalPage] = useState(1);
const { isLoading, isError, refetch } = useQuery(
['data', currentPage],
() => fetchFunction(currentPage),
{
onSuccess: (response) => {
setData((prevData) =>
prevData ? [...prevData, ...response.newsList] : response.newsList
);
setTotalPage(response.totalPages);
},
}
);
const handleLoadMore = () => {
setCurrentPage((prevPage) => prevPage + 1);
};
return {
data,
currentPage,
totalPage,
isLoading,
isError,
handleLoadMore,
isFetching,
};
};
export default useLoadMore;
수정은 했는데 굳이 리액트쿼리를 사용하는 이유가 약한 것 같았다.
useinfinitequery를 사용하면 더보기 기능을 더 쉽게 구현할 수 있다고 하는데, api명세서 내용을 수정해야해서 일단은 원래 구현하려던 방향으로 진행했다.
나중에 가서 후회할까 쫌 걱정스럽긴 하다.
리액트쿼리로 데이터를 불러오면 그 데이터를 중복으로 호출하는 걸 막을 수 있고, 부른 데이터는 캐시로 저장되어 관리가 가능하다고 한다.
그렇다면 써보자
...
const queryClient = useQueryClient();
const getInitialData = useCallback(
(pageNum) => {
const allCachedData = [];
for (let pageIndex = 1; pageIndex <= pageNum; pageIndex++) {
const cachedData = queryClient.getQueryData(['data', pageIndex]);
if (cachedData) {
const dataList = Array.isArray(cachedData.newsList) ? cachedData.newsList : [];
allCachedData.push(...dataList);
}
}
return allCachedData;
},
[queryClient]
);
const cachedData = getInitialData(currentPage);
const { isLoading, isError, refetch } = useQuery(
['data', currentPage],
() => fetchFunction(currentPage),
{
initialData: cachedData,
onSuccess: (response) => {
setData((prevData) =>
prevData ? [...prevData, ...response.newsList] : response.newsList
);
setTotalPage(response.totalPages);
setIsFetching(false);
},
}
);
...
initialData을 사용해서 데이터가 로드 중일때 사전에 이미 저장된 캐시가 있다면 먼저 보여주기로 구현하였다. 있을 때와 없을 때 시각적인 차이가 있다. initialData을 넣으면 기존의 데이터에 이어서 데이터를 부른 것 처럼 보여준다. 없으면 로딩 중에 페이지가 비어있다가 기존 데이터와 새로 부른 데이터를 보여준다. 시각적으로 전자가 보기 좋아서 이 상태로 적용시켰다.