페이지 처리를 하는 방법에는 크게 일반적인 방식, 무한 스크롤 방식 2가지 방법이 있다. 일반적 방식의 페이지 처리 즉 페이지네이션이란 무엇인가??
페이지네이션(Pagination)은 여러 개의 게시물을 보여주는 웹사이트에서 보통 화면 하단에서 볼 수 있는 UI 이다.
페이지 번호를 클릭해서 이동하는 방식의 페이지 처리 방법이다.
게시판 형태의 페이지에서 가장 일반적으로 사용되는 방식.
사용자들은 페이지네이션을 일상적으로 사용하고 있기 때문에 인식하지 못하지만, 사실 페이지네이션 처리를 위해서 다양한 것을 고려해주어야한다.
페이지네이션을 단계적으로 만들면서 고려해야 할 부분들이 있다!
1. page 인자를 사용해서 게시글 목록 불러오기! (fetch
)
2. 페이지 클릭 시 게시글 목록 데이터 다시 불러오기! (refetch
)
refetch
함수란? 페이지 클릭시 해당 페이지에 해당하는 데이터를 다시(re) 불러올(fetch) 하는 것 useQuery에서 data와 함께 refetch 라는 하무를 불러오면 쓸 수 있다.refetch
함수를 넣어주고, refetch
의 인자 에 변경될 variables
(이 경우는 page) 를 입력하자3. map
을 이용해 페이지네이션 뿌리자
{new Array(10).fill(1).map((_, index) => (
<span
onClick={onClickPage}
id={String(index + startPage)}
key={index + startPage}
>
{` ${index + startPage} `}
</span>
))}
이런 경우, 시작 페이지에 해당하는 startPage의 값을 변경해주면 현재 페이지 이후의 10페이지, 이전의 페이지를 불러오는 기능도 구현이 가능.
4. lastPage 설정
게시글의 총 개수를 불러와서 마지막페이지의 값을 구한다!
// lastPage 구하기
const lastPage = Math.ceil(dataBoardsCount?.fetchBoardsCount / 10);
그리고 이전, 다음 페이지를 클릭했을 때 실행되는 함수에 조건을 설정
1페이지 미만 && lastPage가 화면에 출력된 이후 로는 이전, 다음 버튼이 동작하지 않도록 만들어 준다.
map에 조건부 렌더링을 걸어 lastPage보다 큰 숫자는 출력되지 않도록 만들어 준다
{new Array(10).fill(1).map(
(_, index) =>
index + startPage <= lastPage && (
<span
onClick={onClickPage}
id={String(index + startPage)}
key={index + startPage}
>
{` ${index + startPage} `}
</span>
)
)}
5. 이전 페이지, 다음 페이지 이동 시 refetch
11~ 20페이지 라면 11페이지
로 21~30 페이지라면 21페이지
로 게시글 목록이 함께 이동 되어야 한다.
첫 번째 방법은 refetch를 이용
두 번째 방법은 게시글 목록을 불러오기 위하여 useQuery 에 넣는 variables에 startPage라는 state를 넣어주는 방법
이렇게 하면 이전페이지, 다음페이지를 눌러서 startPage가 변경될 때 마다 바뀐 startPage의 데이터가 새로 뿌려지게 된다.
export default function MapBoardPage() {
const [startPage, setStartpage] = useState(1);
const { data, refetch } = useQuery(FETCH_BOARDS);
const { data: dataBoardsCount } = useQuery(FETCH_BOARD_COUNT);
const lastPage = Math.ceil(dataBoardsCount?.fetchBoardsCount / 10);
const onClickPage = (event: any) => {
refetch({ page: Number(event.target.id) });
};
// 이전페이지
const onClickPrevPage = () => {
if (startPage === 1) {
return;
// startPage가 1이라면 조건문으로 return 으로 함수종료
}
setStartpage((perv) => perv - 10); // 뺴기 10
refetch({ page: startPage - 10 });
};
// 다음페이지
const onClickNextPage = () => {
if (startPage + 10 <= lastPage) {
setStartpage((perv) => perv + 10); // 기존에 있던 startpage에 더하기 10해줘
refetch({ page: startPage + 10 });
}
};
return (
<div style={{ margin: "20px" }}>
{data?.fetchBoards.map((el: any) => (
<MyRow key={el._id}>
<MyColumn>{el.writer}</MyColumn>
<MyColumn>{el.title}</MyColumn>
</MyRow>
))}
<span onClick={onClickPrevPage}>< </span>
{new Array(10).fill(1).map((_, index) => {
if (index + startPage <= lastPage) {
return (
<span
key={index + startPage}
id={String(index + startPage)}
onClick={onClickPage}
>
{" "}
{index + startPage}{" "}
</span>
);
} else {
return <span></span>;
}
})}
<span onClick={onClickNextPage}>></span>
</div>
);
}
유튜브 or 페이스북과 같이, 페이지를 아래로 스크롤 하다가 종단점에 도달하면 새로운 데이터가 계속해서 추가되는 방식의 페이지 처리 기법을 무한 스크롤 방식
이라고 한다.
가장 많이 사용되는 두 개의 react 무한 스크롤 라이브러리중
react infinite scroller
를 사용할 것이다.
무한 스크롤 적용하고 싶은 부분을 infiniteScroll
태그를 사용하여 감싼다.
스크롤이 해당 영역 하단 끝에 닿았을 때 실행되어야 할 기능을 함수로 만들어 loadMore 요소에 지정해 주면 된다
Apollo-Client 의 useQuery에서 제공하는 fetchMore
함수를 함께 사용하면 다음 page에 해당하는 데이터를 불러와 기존 데이터 뒤에 붙여 줄 수 있다.
하나의 배열에 하고 싶다.
하나하나 받아와서 맵으로 하나로 합쳐야 하는데 그것이 어려워..
스프레드 연산자를 통해 한다면? 성공!
이 개념을 댓글 무한스크롤로 그대로 가져올 것이다!
원래 있던 페이지 + 받아온 페이지를 합쳐주는 작업을 해줘야한다. (스프레드 연산자를 사용!)
전체 댓글로 합치고 맵으로
돌리면 댓글들을 모두 맵으로
돌릴 수 있다.
스크롤을 내렸을때 특정 함수를 실행 시킬 수 있다.
fetchMore
: refetch랑 같이 fetchMore라는 apollo에서 제공해주는 함수다, 지난번에 패치했던 거 말고 추가로 더 패치해줘!!! 이다.
veriables 를 가지고 패치가 한번 진행되고 updateQuery가 두번째로 실행된다.
updateQuery
: prev, fetchMoreResult 라는 것을 받을 수 있다.
기존 것(fetch)을 냅두고 추가로 패치하겠다(fetchMore)라는 의미!
기존에 있던 1,2,3 페이지는 두고 fetchMore 로 받아온 4 페이지를 받아오겠다.
update. → 스크롤 내릴때마다 실행되게 되어서 댓글들이 계속 추가되어서 보일 수 있도록.
중단점 조건. 추가 댓글이 없다면 이전 댓글들만 업데이트 되어서 보이는 return으로 종료
다음페이지를 veriables
에 넣어서 받아오자
게시물 / 10 하면 페이지 수 인데 다음 페이지를 가져와야하니까 +1
data?.fetchBoardComments
는 보여지고 있는 댓글들.
useWindow → 윈도우 스크롤
가장 가까운 스크롤을 찾아서 실행됨!
div 안에만 무한스크롤 먹이고 싶을때. 쓰기.