게시판에서 글을 보여주는 방법중에 글 목록을 한페이지씩 보여주는 페이지 네이션
과 스크롤 하면 무한으로 스크롤이 내려가면서 목록을 보여주는 무한 스크롤
방식이 있습니다.
이 두 방식을 사용하는 방법을 알아봅시다.
페이지네이션이란 페이지번호를 클릭해서 이동하는 방식의 페이지 처리방법이다.
게시글 목록을 페이지네이션으로 설정하기
스크롤 방식도 페이지네이션이다.
일단 장소는 아까 게시글 페이지네이션의 앞뒤로 들어가줘야하니 span으로 만들어준다.
그리고 span 안에는 클릭 시 이전/다음 페이지로 넘어갈 수 있는 함수를 넣어주기 위해
onClick을 넣어준 뒤 함수를 만들어 바인딩해 준다.
const onClickPrevPage = () => {
};
const onClickNextPage = () => {
};
<span onClick={onClickPrevPage}>이전페이지</span>
{/* 실무에서는 el을 안쓰면 안쓴다는 의미로 _ 를 넣는다. */}
{new Array(10).fill(1).map((_, index) => (
<span
key={index + 1}
id={String(index + 1)}
onClick={onClickPage}
style={{ margin: "10px" }}
>
{index + 1}
</span>
))}
<span onClick={onClickNextPage}>다음페이지</span>
함수 안에는 눌렀을 때 10페이지 뒤/앞으로 가야하기에 useState에 startPage를 기본값 1로 저장하고 누를때마다 10페이지씩 늘어가는 값을 저장하게 해준다. 그리고 이를 refetch해줘야한다.
코드는 아래와 같다.
const [startPage, setStartPage] = useState(1);
const onClickPage = (event: MouseEvent<HTMLSpanElement>) => {
//기다려야하면 async/await 하면 된다.
void refetch({ page: Number(event.currentTarget.id) });
};
const onClickPrevPage = () => {
setStartPage((prev) => prev - 10);
void refetch({ page: startPage - 10 });
};
const onClickNextPage = () => {
setStartPage((prev) => prev + 10);
void refetch({ page: startPage + 10 });
// setStartPage(startPage + 10) 해도 동일하다
};
그러니 아까 map으로 게시글 목록을 부를 때 + 1 했던걸 startPage로 바꿔준다.
<span onClick={onClickPrevPage}>이전페이지</span>
{/* 실무에서는 el을 안쓰면 안쓴다는 의미로 _ 를 넣는다. */}
{new Array(10).fill(1).map((_, index) => (
<span
key={index + startPage}
id={String(index + startPage)}
onClick={onClickPage}
style={{ margin: "10px" }}
>
{index + startPage}
</span>
))}
<span onClick={onClickNextPage}>다음페이지</span>
여기서 문제는 이전 페이지를 계속 누르다보면 없는 페이지도 계속 나오는데 이를 방지해줘야한다.
startPage가 1일 때 이전페이지를 못누르게 하면 이전페이지로 계속 넘어가는 문제는 해결된다.
그런데 다음페이지로 넘어갈 때는 마지막 페이지를 알아야한다.
만약 105페이지가 마지막 페이지라고 하면 110까지만 보여주고 이후에는 다음페이지가 나오면 안된다.
startPage +10 가 lastPage보다 크면 다음페이지가 비활성화되게 한다.
const onClickPrevPage = () => {
if (startPage === 1) return;
setStartPage(startPage - 10);
void refetch({ page: startPage - 10 });
};
const onClickNextPage = () => {
if (startPage + 10 <= lastPage) {
setStartPage(startPage + 10);
void refetch({ page: startPage + 10 });
}
};
<span onClick={onClickPrevPage}>이전페이지</span>
{new Array(10).fill("철수").map(
(_, index) =>
index + startPage <= lastPage && (
<span
key={index + startPage}
id={String(index + startPage)}
onClick={onClickPage}
style={{ margin: "10px" }}
>
{index + startPage}
</span>
)
)}
이걸 해주는 라이브러리 중 유명한게 2가지 있다.
search packages
//웹에서는 심플하다.
react-infinite-scroll-component
//안에 있는 옵션은 둘 다 동일하거나 비슷하다.
2를 사용해보자.
터미널에 설치해준다.
https://www.npmjs.com/package/@storybook/react
여기를 들어가 Getting Started를 보고 설치하면 된다.
yarn add react-infinite-scroller
이때 타입스트립트를 사용하고 있으니 타입스크립트 전용으로 하나 더 설치해준다.
yarn add --dev @types/react-infinite-scroller
import 해준다.
import InfiniteScroll from 'react-infinite-scroller';
스크롤이 되면 fetchmore를 해준다.
export default function StaticRoutedPage() {
const { data, fetchMore } = useQuery<
Pick<IQuery, "fetchBoards">,
IQueryFetchBoardsArgs
>(FETCH_BOARDS);
const onLoadMore = () => {
fetchMore({
variables: { page: 2 },
updateQuery: () => {},
});
};
return (
<InfiniteScroll pageStart={0} loadMore={onLoadMor} hasMore={true}>
{data?.fetchBoards.map((el) => (
<div key={el._id}>
<span style={{ margin: "10px" }}>{el.title}</span>
<span style={{ margin: "10px" }}>{el.contents}</span>
</div>
))}
</InfiniteScroll>
);
}
InfiniteScroll로 감싸준 뒤 속성 pageStart={0} loadMore={onLoadMor} hasMore={true} 을 적어준다.
상황에 맞는 페이지 로드 방법을 활용하면 좋겠습니다.