▼ 설치
react infinite scroller
react infinite scroll component
yarn add react-infinite-scroller
타입스크립트 오류시 yarn add -dev @types/react-infinite-scroller
: 페이지를 아래로 스크롤 하다가 종단점에 도달하면
새로운 데이터가 계속해서 추가되는 페이지 처리 방법
[실습 section16]
- import해오기 / grapql요청 및 스타일 지정하기
import { useQuery, gql } from "@apollo/client"; import type { IQuery, IQueryFetchBoardsArgs, } from "../../src/commons/types/generated/types"; import InfiniteScroll from "react-infinite-scroller"; import styled from "@emotion/styled"; const FETCH_BOARDS = gql` query fetchBoards($page: Int) { fetchBoards(page: $page) { _id writer title contents } } `; const Wrapper = styled.div` height: 500px; overflow: auto; `;
- 게시글 데이터와 fetchmore기능을 위한 선언
export default function StaticRoutingMovedPage(): JSX.Element { //어떤 페이지를 더 패치할 것인지!! const { data, fetchMore } = useQuery< Pick<IQuery, "fetchBoards">, IQueryFetchBoardsArgs (FETCH_BOARDS);
- 스크롤이 페이지 하단 끝에 닿을 때 실행할 기능을 onLoarMore함수로 만들기
const onLoadMore = (): void => { if (data === undefined) return; void fetchMore({ //page : 패치모어로 패치할 페이지 = 다음페이지(+1) 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], }; }, }); };
->onLoadMore 함수 최상위에 data가 없으면 실행하지 않도록 if문을 추가한다.
-> useQuery에서 제공하는fetchMore
함수를 함께 사용해
다음 page에 해당하는 데이터를 불러와 기존 데이터 뒤에 이어지도록 붙여 줄 수 있다.
-> 조건문으로 마지막으로 받아올 추가데이터가 없다면(리패치할 것이 없다면) 기존댓글,
추가데이터 있으면 기존(이전)댓글 + 추가댓글을 리턴!
-> 무한스크롤 적용하고 싶은 영역을 InfiniteScroll로 감싼다.
- table형태로 완성한 결과
import { useQuery, gql } from "@apollo/client"; import type { IQuery, IQueryFetchBoardsArgs, } from "../../src/commons/types/generated/types"; import InfiniteScroll from "react-infinite-scroller"; import styled from "@emotion/styled"; const FETCH_BOARDS = gql` query fetchBoards($page: Int) { fetchBoards(page: $page) { _id writer title contents } } `; const Wrapper = styled.div` height: 500px; overflow: auto; `; 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 ( <Wrapper> <InfiniteScroll pageStart={0} loadMore={onLoadMore} hasMore={true} useWindow={false} <table className="table"> <th>제목</th> <th>이름</th> <th>내용</th> {data?.fetchBoards.map((el) => ( <tr key={el._id}> <td style={{ margin: "10px", border: "solid" }}>{el.title}</td> <td style={{ margin: "10px", border: "solid" }}>{el.writer}</td> <td style={{ margin: "10px", border: "solid" }}>{el.contents}</td> </tr> )) ?? <div></div>} </table> </InfiniteScroll> </Wrapper> ); }