주의 이 글은 기본적인 react-query 사용법을 알고 보시는것을 추천드립니다.
react에서 react-query를 이용한 무한 스크롤을 구현해보자
일반적으로 react-query를 이용해 서버 상태를 관리할때 useQuery
를 사용한다. 내가 작성한 뉴욕 타임즈 api를 활용한 부분에서 예를 들어보겠다. (Github : https://github.com/seungjun0423/times-scrap)
import { useInfiniteQuery } from "@tanstack/react-query";
const {
data
} = useInfiniteQuery({
queryKey:['todayHeadline'],
queryFn: ({pageParam})=>fetchFn({pageParam}),
});
위 코드를 컴포넌트 내에서 사용해주면 간단히 데이터를 가져올 수 있다. react-query의 여러 특성을 설명하면 글이 길어지니 내가 공부하며 느꼈던 특이한점 한가지만 적자면 여기서 실질적으로 데이터를 호출하는 함수인 fetchFn
(axios 또는 fetch등을 이용해 직접 서버와 통신하는 함수)은 react-query에서 비동기 관련 작업들을 해주기 때문에 async,await 등 비동기적으로 작성해줄 필요가 없다. 그냥 Promise를 반환해주면 data로 선언한 부분을 이용해 response를 받아올 수 있다.
어쩄든 기본 방식이 위의 useQuery
이고 이와 함께 useEffect
를 사용해 무한 스크롤을 구현할 수도 있다. 하지만, react-query에서는 무한스크롤을 간편하게 구현할 수 있도록 useInfiniteQuery
라는 기능을 제공한다.
위 코드를 useInfiniteQuery
로 바꿔보면 아래와 같다.
import { useInfiniteQuery } from "@tanstack/react-query";
const {
data,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
} = useInfiniteQuery({
queryKey:['todayHeadline'],
queryFn: ({pageParam})=>fetchFn({pageParam}),
getNextPageParam: ( lastPage, allPages ) => Number(allPages.length)+1,
});
여기서 중요한 점은 getNextPageParam: (lastPage, allPages) => unknown | undefined
이 부분이다. 이 부분을 중점적으로 코드를 살펴보자
getNextPageParam(lastPage, allPages) :
lastPage : 지금껏 요청한 모든 데이터중 가장 마지막에 받아온 데이터
allPages : 모든 데이터 요청의 parameter 배열
isFetchingNextPage : boolean 값을 리턴하며 이름 그대로 다음 데이터 요청이 진행중인지 알려준다
fetchNextPage : getNextPageParam에서 리턴해주는 다음 요청을 위한 parameter를 받고 이를 fetchFn의 인자로 넣어서 실행시켜준다.
hasNextPage : boolean 값을 리턴하며 요청할 다음 데이터가 있는지 판단한다.
여기 까지 작성하면 react-query에서 필요한 부분은 모두 작성되었다. 이후 IntersectionObserver API
를 이용해 아래의 코드를 작성하고 Ref dom을 붙이면 끝! 이부분도 하고 싶은 말이 많지만 우선 react-query 글이기에 이정도만 이야기 하겠다.
useEffect(() => {
if (loadingRef.current && hasNextPage) {
const observer = new IntersectionObserver(
entries =>
entries[0].isIntersecting && fetchNextPage(),
{ threshold: 1 }
);
observer.observe(loadingRef.current);
return () => observer.disconnect();
}
}, [hasNextPage]);