리액트 환경의 무한 스크롤
무한 스크롤은 페이지 하단 영역까지 스크롤될 경우 다른 컨텐츠를 새롭게 로딩해 페이지에 추가되는 방식이다.
react-intersection-observer 라이브러리를 사용해서 구현해보았다.
- 라이브러리 설치
$ npm install react-intersection-observer --save
- useInView hook
const { ref: observerRef, inView } = useInView()
=> 관찰하는 객체 (observer) 하나를 ref로 설정한 후 해당하는 객체가 화면에 보이면 특정 코드를 실행시킬 수 있다.
https://github.com/thebuilder/react-intersection-observer
GitHub - thebuilder/react-intersection-observer: React implementation of the Intersection Observer API to tell you when an eleme
React implementation of the Intersection Observer API to tell you when an element enters or leaves the viewport. - thebuilder/react-intersection-observer
github.com
- 전체 코드
import { useInView } from 'react-intersection-observer'
const Bookmark = () => {
const { ref: observerRef, inView } = useInView()
React.useEffect(() => {
if (inView) {
const totalPage = queryBookmarks.data.totalPage
if (totalPage != null && bookmarkPage < totalPage) {
// 뷰포트에 들어오면 count + 1 해주기
setBookmarkPage((prev) => prev + 1)
}
}
}, [inView])
return (
<div>
<div>
{items.map((item) => (
<BookmarkItem
title={bookmark.title}
...
/>
)}
</div>
<div ref={observerRef} />
</div>
)
}
문제 상황
useInView의 observerRef가 뷰포트에 들어올 때마다 inView 상태가 갱신되는 방식으로 구현을 했는데,
페이지가 다시 로딩하는 문제가 일어났다.
이유는 무한 스크롤이나 하단에 위치한 요소가 여러 번 감지되면 이런 문제가 발생하는데, observerRef가 계속해서 inView 상태를 변경하기 때문이다.
해결법
useInView의 triggerOnce 옵션을 활용하여 한 번만 실행할 수 있도록 하자.
triggerOnce: true를 설정하면, 한 번 감지된 이후에는 inView 상태가 유지되어, 반복적으로 호출되지 않도록 제어할 수 있다.
const { ref: observerRef, inView } = useInView({
triggerOnce: true, // 추가
});
return (
<div>
{inView && ( // 추가
<div>
<BookmarkItem
...
/>
<div ref={observerRef} />
</div>
}
</div>
)
추가로 inView가 True 일 때만 해당 아이템이 보이도록 구현한다.
'React' 카테고리의 다른 글
[React] Reactstrap Layout - Grid System (0) | 2024.01.22 |
---|---|
React 상태 관리 라이브러리 (feat. Context API, Redux, Recoil) (0) | 2023.08.25 |