연관 내용
[페이지네이션 적용하기]
fetchMore
을 활용해서 이전 댓글과 추가된 댓글의 배열을 연결한다.react-infinite-scroller와 react infinite scroll component 둘 다 많이 쓰이고, 사용 방법도 거의 유사하다.
설치할 디렉토리의 터미널에 입력한다.
yarn add react-infinite-scroller
위 에러는 타입 스크립트를 설치하라는 뜻이다.
yarn add @types/react-infinite-scroller --dev
👈🏻 터미널에 입력 ㄱㄱ
사용할 파일에 import한다.
import InfiniteScroll from 'react-infinite-scroller';
loadMore: 더 있으면 스크롤을 내릴 때 작동시킬 함수를 넣는다.
{loadFunc} : 스크롤을 내리면 실행될 함수 -> 만들어서 넣어줘야 한다.
hasmore : 데이터가 더 있는지 없는지
loader : 스크롤이 로딩되는 동안 보여줄 내용
{items} : 맵으로 그려주는 데이터를 넣으면 된다.
useWindow={false}를 추가하면 윈도우 창 자체가 아닌 컴포넌트 안에 스크롤이 생긴다.
컴포넌트를 감싸는 태그에 height:700px; overflow:auto
추가!
추가 요청을 위해 variables를 수정해야 하는지 확인한다.
보통 조회할 페이지를 의미하는 값으로 쿼리 요청을 보낸다.
export const FETCH_BOARD_COMMENTS = gql`
query fetchBoardComments($boardId: ID!, $page: Int) {
fetchBoardComments(boardId: $boardId, page: $page) {
_id
writer
rating
contents
createdAt
}
}
`;
const onLoadMore = () => {
// 데이터가 없으면 실행하지 않는다. (처음에 데이터가 undefined일 때 무한 스크롤이 실행 되는 것을 방지하기 위함)
if (data === undefined) return;
void fetchMore({
variables: {
// 다음 페이지(불러올 페이지) : 기존에 받아온 data에서 길이를 가져와서 활용한다.
page: Math.ceil((data?.fetchBoards.length ?? 10) / 10) + 1
},
// useQuery로 받아온 data를 update한다.
updateQuery: (prev, { fetchMoreResult }) => {
// prev: 기존의 data
// {fetchMoreResult} : 추가로 요청해서 받아온 내용
// 새로 조회해온 값이 없으면 기존 것을 그대로 업데이트한다.
if (fetchMoreResult.fetchBoards === undefined)
return { fetchBoardComments: [...prev.fetchBoardComments] };
// 가져온 내용으로 return (update한다.)
return {
// 기존의 것과 추가로 받은 것을 합친다.
fetchBoardComments: [
...prev.fetchBoardComments,
...fetchMoreResult?.fetchBoardComments,
],
};
},
});
};
<InfiniteScroll>
로 감싼다.hasmore = {true}
로 변경loadMore
에 바인딩<S.CListWrapper
commentsLength={props?.data ? props.data.fetchBoardComments.length : 0}
>
<InfiniteScroll
pageStart={0}
loadMore={props.onLoadMore}
hasMore={true}
useWindow={false}
>
{props.data?.fetchBoardComments.map((el: any, index: number) => (
<CommentsItemUI
key={el._id}
el={el}
data={props.data}
onToggleModal={props.onToggleModal}
onClickDelete={props.onClickDelete}
isOpen={props.isOpen}
onChangePassword={props.onChangePassword}
index={index}
/>
)) ?? <div></div>}
</InfiniteScroll>
</S.CListWrapper>
🚨 ERROR
Warning: Failed prop type: The propchildren
is marked as required inInfiniteScroll
, but its value isundefined
.화면에 댓글은 잘 나오는데 위와 같은 콘솔 에러가 뜰 경우
👉🏻 데이터가 없을 경우 빈 태그를 보여주도록 처리하면 해결됨!
전체 코드
import { useQuery, gql } from "@apollo/client";
import {
IQuery,
IQueryFetchBoardsArgs,
} from "../../../src/commons/types/generated/types";
import InfiniteScroll from "react-infinite-scroller";
const FETCH_BOARDS = gql`
query fetchBoards($page: Int) {
fetchBoards(page: $page) {
_id
writer
title
contents
}
}
`;
export default function StaticRoutingMovedPage(): JSX.Element {
const { data, fetchMore } = useQuery<
Pick<IQuery, "fetchBoards">,
IQueryFetchBoardsArgs
>(FETCH_BOARDS);
const onLoadMore = (): void => {
if (data === undefined) return;
void fetchMore({
variables: { page: Math.ceil((data?.fetchBoards.length ?? 10) / 10) + 1 },
updateQuery: (prev, { fetchMoreResult }) => {
if (fetchMoreResult.fetchBoards === undefined)
return { fetchBoards: [...prev.fetchBoards] };
return {
fetchBoards: [...prev.fetchBoards, ...fetchMoreResult.fetchBoards],
};
},
});
};
return (
<div>
<InfiniteScroll pageStart={0} loadMore={onLoadMore} hasMore={true}>
{data?.fetchBoards.map((el) => (
<div key={el._id}>
<span>{el.title}</span>
<span>{el.writer}</span>
</div>
)) ?? <div></div>}
</InfiniteScroll>
</div>
);
}