Pagination vs Infinite Scroll

Kingmo·2022년 4월 2일
0

페이지 처리를 하는 방법에는 크게
일반적인 Pagination 방식과 Infinite Scroll 방식이 있다.

1. Pagination

Pagination은 사진과 같은 페이지 번호를 클릭해서 번호에 해당하는 페이지로 이동하는 방식이다.
이를 구현해보자.
코드에 대한 자세한 설명은 주석으로 적었다.

// 시작 페이지값을 알려줄 state
const [startPage, setStartPage] = useState(1)

// dataBoardsCount에는 전체 게시물 갯수가 담겨있다 10으로 나눠 올림하면
// 한 페이지에 게시글을 10개씩 보여줄 때 마지막 페이지의 번호가 lastPage에 할당된다.
const lastPage = Math.ceil(dataBoardsCount?.fetchBoardsCount / 10);

// 페이지 네비게이션을 눌렀을 때 화면을 해당 페이지값으로 재구현 해줄 함수
const onClickPage = (event) => {
  	// 클릭한 요소의 event.target이 있으면
	if (event.target instanceof Element)
      // page에 event.targe.id를 넣고 refetch 하기
      refetch({ page: Number(event.target.id) })
}

// 페이지 네비게이션 이전 목록
const onClickPrevPage = () => {
  // 페이지는 1페이지 이하로 내려가면 안되기 때문에 이를 예외처리
  if (startPage === 1) return;
  // 이전 페이지 버튼을 누를 때 마다 startPage가 10 감소
  setStartPage((prev) => prev - 10)
}

// 페이지 네비게이션 다음 목록
const onClickNextPage = () => {
	// 10페이지씩 목록을 보여주고, 마지막 페이지 이후로 페이지가 넘어가지 않게 예외처리
  	if (startPage + 10 > lastPage) return;
  	// 다음 페이지 버튼을 누를 대마다 startPage가 10 증가
  	setStartPage((prev) => prev + 10)
}

// map()을 이용해 게시물 데이터를 뿌려주기
<div>
  {/* data.fetchBoards배열에 담긴 객체들을 하나 씩 뽑아 화면에 뿌려주기 map 함수를 ()소괄호로 감싸 리턴하여 화면에 그리기*/}
  {data?.fetchBoards.map((el) => (
  	<div key={el._id}>
      {el.title} {el.writer}  
    </div>
  ))}
</div>

// 페이지 이동을 위한 네비게이션 생성
<span onClick={onClickPrevPage}>{`<`}</span>
  {/* 길이가 10인 빈 배열을 만든 후 요소들을 1로 채워 map이 작동하도록 처리 (페이지 목록에 페이지 번호를 10개씩 보여 줌)*/}
  {/* 마지막 페이지를 넘어가는 페이지는 보여줄 수 없기에 이를 예외처리 */}
  {new Array(10).fill(1).map((_, i) => startPage + i <= lastPage && (
    {/* react에서는 key값에 대응하는 데이터를 화면에 보여주기 때문에 고유한 key을 넣어줘야한다. */}
    <span
      key={startPage + i}
      onClick={onClickPage}
      id={String(startPage + i)}
      style={{ margin: "10px", cursor: "pointer" }}
    >
      {startPage + i}
</span> ))}
<span onClick={onClickNextPage}>{`>`}</span>

2. Infinite Scroll(무한스크롤)

유튜브 또는 페이스북과 같이 아래로 스크롤할 때마다 댓글이 있다면 계속해서 추가해 보여주는 방식의 페이지 처리방법이다.

react에서는 주로 react-infinite-scroller를 사용한다.
이는yarn add react-infinite-scroller으로 설치한다.
타입스크립트를 사용 중이라면 추가로 yarn add @types/react-infinite-scroller --dev
명령어로 추가 패키지를 설치한다.

이를 구현해보자.
코드에 대한 자세한 설명은 주석으로 적었다.

import { useQuery, gql } from "@apollo/client";
import InfiniteScroll from "react-infinite-scroller";

// 게시글 목록을 가져오는 query 문
const FETCH_BOARDS = gql`
  query fetchBoards($page: Int) {
    fetchBoards(page: $page) {
      _id
      writer
      title
      contents
    }
  }
`;

export default function MapBoardPage() {
  const { data, fetchMore } = useQuery(FETCH_BOARDS);

  const onLoadMore = () => {
    // useQuery로 받아온 데이터가 없을 경우 예외처리
    if (!data) return;

    // prev.fetchBoards : 이전에 받아온 게시글 목록
    // fetchMoreResult.fetchBoards : 스크롤이 일정 하단 부분에 닿았을 때 생성한 게시글 목록
    fetchMore({
      // 페이지 번호에 해당하는 게시물 조회
      variables: { page: Math.ceil(data?.fetchBoards.length / 10) },
      updateQuery: (prev, { fetchMoreResult }) => {
        // 더 받아올 데이터가 없을 경우 예외처리
        if (!fetchMoreResult.fetchBoards)
          return { fetchBoards: [...prev.fetchBoards] };
    	// 기존 배열의 형식 그대로 이어지게 하기위해 스프레드 연산자로 연결한다.
        return {
          fetchBoards: [...prev.fetchBoards, ...fetchMoreResult.fetchBoards],
        };
      },
    });
  };

  return (
    // loadMore={onLoadMore} 스크롤이 일정 하단 부분에 닿았을때 onLoadMore()함수 실행
    // hasMore={true} 스크롤이 일정 하단 부분에 닿았을때 loadMore을 실행할지 말지를 true , false로 결정한다.
    <InfiniteScroll pageStart={0} loadMore={onLoadMore} hasMore={true}>
      {data?.fetchBoards.map((el) => (
        <MyRow key={el._id}>
          <MyColumn>{el._id}</MyColumn>
          <MyColumn>{el.writer}</MyColumn>
          <MyColumn>{el.title}</MyColumn>
        </MyRow>
      )) || <div></div>}
    </InfiniteScroll>
  );
}

profile
Developer

0개의 댓글