SWR에는 useSWRInfinite hook이 존재합니다. 이를 이용해서 무한스크롤을 쉽게 만들 수 있는데요, 같이 볼게요!
const {
data, // 받아오는 데이터
size, // 현재 페이지가 어디인지,
setSize, // +1 해 주면 다음 요청 보낼 수 있도록
} = useSWRInfinite<Response>(
(page: number) => `/api/url?page=${page + 1}`
);
useSWRInfinite에는 size와 setSize라는 인자를 받아올 수 있습니다 이는 주석처럼 현재 페이지가 어디인지, 그리고 끝에 도달했을 때 다음 페이지를 읽어줄 수 있도록 변경 함수를 사용할 수 있습니다
이 때 주의해야 할 점은 useSWRInfinite를 사용해서 데이터를 가져오게 되면 배열에 한 번 더 감싸져서 반환하기 때문에 .flat
함수를 사용하거나, lodash에 있는 flatten
함수를 사용해 벗겨준 후 사용해 주어야 합니다.
const listData = flatten(data?.map((item) => item.data));
// map을 사용한 이유는 필요한 데이터만 꺼내서 사용하기 위함
그리고 무한스크롤의 원리는 유저가 어떤 요소에 접근했을 때 다음 데이터를 불러와 보여주는 것인데 useRef를 사용하는 방법도 있겠지만 오늘은 react-intersection-observer 라이브러리를 같이 사용해볼 예정입니다.
$ npm install react-intersection-observer
우선 패키지를 설치해 줍니다 (모노레포 사용하는 분들은 뒤에 프로젝트 네임 붙여주셔야 해요! 자세한 내용은 모노레포 글을 참고해주세요!
{size < (meta?.lastPage ?? 0) && ( // 현재 페이지가 라스트 페이지보다 작으면 실행될 수 있도록
<InView
className="flex h-[80px] items-center justify-center"
onChange={(inView) => {
if (inView && size < (meta.lastPage ?? 0)) {
setSize(size + 1);
}
}}
>
<Spinner />
</InView>
)}
InView 컴포넌트를 컴포넌트에 심어줌으로 유저가 이 컴포넌트에 도달했음을 확인할 수 있습니다.
이 라이브러리에 대한 이해는 사진을 보면 더 빠르게 할 수 있을 것 같은데요,
이런 설정값들을 사용할 수 있는 라이브러리입니다. 그렇기 때문에 무한 스크롤을 사용할 때 유용하게 쓰일 수 있는 것 같아요!
감사합니다. SWR로 무한 스크롤을 구현 중인데 큰 도움이 되었읍니다.
라이브러리 없이 구현하는 방법도 올려주시면 좋을 것 같아요