Slog
Sign in

React로 무한 스크롤 구현하기

2020 Nov 3
3 min read
React로 무한 스크롤 구현하기

이번에는 react-intersection-observer를 이용해서 무한 스크롤을 구현하는 방법을 알아가보도록 하겠습니다.

들어가기 앞서

image

많은 콘텐츠를 효과적으로 보여줄 수 있는 대표적 UI 에는 무한 스크롤, 페이징 이 있습니다.

PC에서는 페이징, 모바일에서는 무한 스크롤 UI 가 각각 더 사용자에게 편하게 다가옵니다. 하지만 최근에는 반응형 페이지를 통해서 PC와 모바일 모두 커버하는 경우가 많기 때문에 이번에는 무한 스크롤 을 함께 구현해보도록 하겠습니다.

구현

무한 스크롤을 구현하는 방법은 여러가지가 있겠지만, 가장 확실한 방법은 마지막 요소가 사용자에게 보이면 다음 데이터를 불러오는 방법이 있습니다.
react-intersection-observer 라이브러리를 사용하면 위와 같은 방법을 보다 쉽게 구현할 수 있습니다.

설치

yarn add react-intersection-observer

또는

npm i react-intersection-observer

사용 방법

import React from "react"
import { useInView } from "react-intersection-observer"

const App = () => {
  const [ref, inView] = useInView()

  return (
    <div ref={ref}>
      Element {inView.toString()}
    </div>
  )
}

export default App

ref 를 div에 걸어주면 해당 요소가 보이면 inView가 true 로, 안 보이면 false로 자동으로 변경됩니다.

직접 보기

예제

// App.js
import React, { useState, useEffect, useCallback } from "react"
import { useInView } from "react-intersection-observer"
import axios from "axios"

const App = () => {
  const [items, setItems] = useState([])
  const [page, setPage] = useState(1)
  const [loading, setLoading] = useState(false)

  const [ref, inView] = useInView()

  // 서버에서 아이템을 가지고 오는 함수
  const getItems = useCallback(async () => {
    setLoading(true)
    await axios.get(`${Your Server Url}/page=${page}`).then((res) => {
      setItems(prevState => [...prevState, res])
    })
    setLoading(false)
  }, [page])

  // `getItems` 가 바뀔 때 마다 함수 실행
  useEffect(() => {
    getItems()
  }, [getItems])

  useEffect(() => {
    // 사용자가 마지막 요소를 보고 있고, 로딩 중이 아니라면
    if (inView && !loading) {
      setPage(prevState => prevState + 1)
    }
  }, [inView, loading])

  return (
    <div className="list">
      {items.map((item, idx) => (
        <React.Fragment key={idx}>
          {items.length - 1 == idx ? (
            <div className="list-item" ref={ref}>
              {item.content}
            </div>
          ) : (
            <div className="list-item">
              {item.content}
            </div>
          )
        </React.Fragment>
      ))

간단하게 예제를 만들어 보았습니다. 차근차근 코드를 보도록 하죠.

getItems 함수는 page 가 바뀔 때 마다 재생성 되는 함수입니다. 이 함수를 useEffect 에 대괄호 안에 넣어 getItems 함수가 바뀔 때 마다 getItems 를 실행하도록 하였습니다.

결론적으로 page 가 바뀔 때 마다 서버에 정보를 요청합니다. 다음 페이지를 불러오기 위해서는 page 만 증가시키면 바로 다음 페이지에 관한 정보를 받아옵니다.

두 번째 useEffectinView 가 바뀔 때마다 inViewtrue 이고, 로딩중이 아니라면 page 를 증가시킵니다.

마치며

스크롤을 계산하여 데이터를 불러오는 무한 스크롤 방식은 아이폰에서의 스크롤 이벤트가 다르게 적용되어 생각보다 까다로운 부분들이 많았는데 이 글을 보고 react-intersection-observer 를 사용하여 보다 쉽게 구현할 수 있었으면 좋겠습니다.

Explore Popular Contents

0 Comments

Anonymous