[React] Intersection Observer를 사용한 무한 스크롤 구현

GONI·2021년 12월 24일
1
post-thumbnail

항상 이론으로만 보다가, 한번쯤 직접 구현해보고 싶어서 제일 쉬운 예제를 따라해보았다.
(간단하게 기능만 구현하기위해 any type을 남발하였음...)

API 출처: https://unsplash.com/


1. 상태 정의

const [photos, setPhotos] = useState<any>([])
const [pageNumber, setPageNumber] = useState<number>(1)

photo: 불러온 데이터를 저장
pageNumber: 불러올 API의 page query


2. pageNumber를 인자로 받는 fetch 함수를 구현

const fetchPhotos = async (pageNumber: number) => {
    const res = await fetch(`${API_URL}=${Access_Key}&page=${pageNumber}`)
    const data = await res.json()
    setPhotos((photo: any) => [...photo, ...data])
}

3. pageNumber에 따른 fetch함수 업데이트

useEffect(() => {
    fetchPhotos(pageNumber)
}, [pageNumber])

4. pageNumber를 늘리면서 load하는 함수를 구현

const loadMore = () => setPageNumber((prev) => prev + 1)

쉽게 생각하여 버튼에 onClick속성으로 loadMore함수를 작성해주면, 버튼을 누를 때 데이터를 불러오게 되는 것이다.

이렇게 되면 무한 스크롤은 아니지만 버튼 클릭에 따른 데이터 불러오기는 할 수 있다. 이렇게 세팅을 완료한 후 Intersection Observer를 통해 무한 스크롤을 본격적으로 구현해 보도록 하자.


5. Intersection Observer 적용(드디어?)

const pageEnd = useRef<any>()

useEffect(() => {
    const observer = new IntersectionObserver((entries: any) => {
        if (entries[0].isIntersecting) {
          loadMore()
        }
      }, { threshold: 1 })
    observer.observe(pageEnd?.current)
}, [])

여기서 entries, 즉 entries[0].isIntersecting는 useRef를 통해 div에서 ref로 지정한 블록에 닿을 때 true, 그렇지 않을 때 false값이 나온다.

쉽게 말해서 마지막 블록에 닿아서 loading이 필요할 때 entries[0].isIntersecting : true,
그 외의 경우는 entries[0].isIntersecting : false값이라는 말이다.
그렇기 때문에 entries[0].isIntersecting가 true일 때 loadMore함수를 실행시켜 주는 것이다.

아까와 흐름은 동일하지만 이번엔 버튼을 눌렀을 때 loadMore함수가 실행되는것이 아닌, 버튼을 감싸는 div가 화면에 잡혀서 끝날 경우 loadMore함수가 실행되는 것을 볼 수 있다. 그렇게 되면 아주 간단하게나마 무한스크롤을 구현할 수 있다!

root, rootMargin, threshold 등 여러 옵션이 있지만 해당 포스팅에서는 기본적인 것만 구현하였으므로 다른 옵션들이 궁금하다면 공식문서를 참고하도록 해보자!

profile
오로지 나의 기억력을 위한 일지

0개의 댓글