[react-infinite-scroller] 무한스크롤 적용하기
2023. 2. 2. 18:50ㆍNext.js
728x90
반응형
무한스크롤
- 스프레드 연산자와 useQuery의
fetchMore
을 활용해서 이전 댓글과 추가된 댓글의 배열을 연결한다.
fetchMore 속성 설명
- variables : 새롭게 요청할 쿼리의 입력값
- updateQuery : 기존에 저장된 query를 업데이트 한다.
- prev: 이전 요청까지의 데이터
- fetchMoreResult: 새롭게 가져온 데이터
- return의 fetchBoardComments가 새로 저장한 값으로 업데이트 된다.
라이브러리 설치
react-infinite-scroller와 react infinite scroll component 둘 다 많이 쓰이고, 사용 방법도 거의 유사하다.
1. react-infinite-scroller 설치
설치할 디렉토리의 터미널에 입력한다.yarn add react-infinite-scroller
2. @types/react-infinite-scroller 설치
위 에러는 타입 스크립트를 설치하라는 뜻이다.yarn add @types/react-infinite-scroller --dev
👈🏻 터미널에 입력 ㄱㄱ
3. import
사용할 파일에 import한다.import InfiniteScroll from 'react-infinite-scroller';
사용 방법
0. 속성 설명
- loadMore: 더 있으면 스크롤을 내릴 때 작동시킬 함수를 넣는다.
{loadFunc} : 스크롤을 내리면 실행될 함수 -> 만들어서 넣어줘야 한다. - hasmore : 데이터가 더 있는지 없는지
- loader : 스크롤이 로딩되는 동안 보여줄 내용
- {items} : 맵으로 그려주는 데이터를 넣으면 된다.
- useWindow={false}를 추가하면 윈도우 창 자체가 아닌 컴포넌트 안에 스크롤이 생긴다.
컴포넌트를 감싸는 태그에height:700px; overflow:auto
추가!
1. Query를 수정한다.
추가 요청을 위해 variables를 수정해야 하는지 확인한다.
보통 조회할 페이지를 의미하는 값으로 쿼리 요청을 보낸다.
export const FETCH_BOARD_COMMENTS = gql`
query fetchBoardComments($boardId: ID!, $page: Int) {
fetchBoardComments(boardId: $boardId, page: $page) {
_id
writer
rating
contents
createdAt
}
}
`;
2. 스크롤을 내릴 때 실행시킬 함수를 만든다.
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,
],
};
},
});
};
3. 무한스크롤을 적용시킬 부분을 <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 prop children
is marked as required in InfiniteScroll
, but its value is undefined
.
화면에 댓글은 잘 나오는데 위와 같은 콘솔 에러가 뜰 경우
👉🏻 데이터가 없을 경우 빈 태그를 보여주도록 처리하면 해결됨!
전체 코드
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>
);
}
728x90
반응형
'Next.js' 카테고리의 다른 글
[Firebase] 프론트엔드에서 DB 다루기 (1) | 2023.02.03 |
---|---|
[GraphQL] GraphQL Code Generator로 TypeScript 지정하기 (0) | 2023.01.20 |
[Next.js] Typescript 설치하기 (0) | 2023.01.19 |