[7/25 TIL] 리액트쿼리를 사용해서 더보기 기능 구현

haegnim·2023년 7월 25일

TIL

목록 보기
44/52

어제까지 리액트쿼리를 사용하지 않고 더보기 기능을 구현했었다. 리액트쿼리를 사용할 거면 조회할 때 써보시라고 권해주셔서 코드를 수정하기로 하였다.

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을 넣으면 기존의 데이터에 이어서 데이터를 부른 것 처럼 보여준다. 없으면 로딩 중에 페이지가 비어있다가 기존 데이터와 새로 부른 데이터를 보여준다. 시각적으로 전자가 보기 좋아서 이 상태로 적용시켰다.

0개의 댓글