nextjs + apollo + mongodb pagination 구현

HyosikPark·2020년 12월 30일
0

next.js+graphql+mongodb

목록 보기
3/3
post-custom-banner

현재페이지 : curPage
전체 게시물 : postCount
한 페이지 당 15개의 게시물을 불러온다.
페이지수는 10개씩 끊어서 나타낸다.
next-with-apollo lib을 사용하여 getInitialProps에서 post들을 ssr로 받아온다.
<< : 가장 처음으로
< : 페이지 묶음 이동 ex) 11~20 -> 1~10
`>> : 가장 마지막으로 이동
'> : 페이지 묶음 이동 ex) 1~10 => 11~20

mongodb 게시물 끊어서 가져오기.



 Query: {
    async allPosts(_, { category, curPage }, ctx) {
      const db = ctx.db.collection(category);
      const posts = await db
        .find()
        .sort({ createdAt: -1 })
        .skip(15 * (curPage - 1))
        .limit(15)
        .toArray()
        .catch((e) => {
          throw new Error('An error occurred while loading the data.');
        });

      const count = await db.countDocuments();
      return { postInfo: posts, postCount: count };
    },
  },
    

sort({key: -1 or 1}) : key를 기준으로 -1은 내림차순.
skip(number) : 처음부터 number만큼 field를 무시한다.
limit(15) : 15개씩 끊어서 받아오기.

db.countDocuments() : collection의 전체 field 가져옴.

front에서 pagination 구현

현재 페이지에 따라 UI에 나타낼 번호 배열 구현.
현재페이지가가 1~10이면 1~10까지, 11~20이면 11~20까지 나타낸다. 만약 전체게시물의 개수가 10 * 15 = 150의 배수로 딱 떨어지지 않을 경우 마지막페이지가 중간에 끊길수 있기 떄문에 ex) 11~13 구현하기가 까다로웠다.

function pageNums(postCount: number, curPage: number) {
  let arr = [];
  const calc1 = Math.ceil(curPage / 10);
  const restPage = postCount - 150 * (calc1 - 1);
  const calc2 = Math.ceil(restPage / 15);

  let initPage = 10 * calc1 - 9;
  const lastPage = calc2 >= 10 ? initPage + 9 : initPage + calc2 - 1;

  while (initPage <= lastPage) {
    arr.push(initPage);
    initPage++;
  }

  return arr;
}

.....

 {pageNums(postCount, curPage).map((e) => (
              <li key={e} className={`${e}page page_button`}>
                {e}
              </li>
            ))}

<< : 가장 처음으로
< : 페이지 묶음 이동 ex) 11~20 -> 1~10
`>> : 가장 마지막으로 이동
'> : 페이지 묶음 이동 ex) 1~10 => 11~20

현재페이지가 1일 경우 << 비활성화.
현재페이지가 1~10일경우 < 비활성화.
현재페이지가 마지막페이지일 경우 >> 비활성화
현재페이지가 마지막페이지 대에 있을 경우 > 비활성화.

 const lastPage = Math.ceil(postCount / 15);

...
return 
// << 비활성화 여부
{curPage <= 1 ? null : (
              <li className='angle_double_left page_button'>
                <FontAwesomeIcon icon={faAngleDoubleLeft} />
              </li>
            )}
// < 비활성화 여부

            {curPage <= 10 ? null : (
              <li className='angle_left page_button'>
                <FontAwesomeIcon icon={faAngleLeft} />
              </li>
            )}

// > 비활성화 여부          
            {curPage >= Math.floor((lastPage - 1) / 10) * 10 + 1 ? null : (
              <li className='angle_right page_button'>
                <FontAwesomeIcon icon={faAngleRight} />
              </li>
            )}
// >> 비활성화 여부
            {Math.ceil(postCount / 15) == curPage ? null : (
              <li className='angle_double_right page_button'>
                <FontAwesomeIcon icon={faAngleDoubleRight} />
              </li>
            )}
post-custom-banner

0개의 댓글