오늘의 집 페이지에서 footer를 보려고 스크롤을 내려봤다.
오우 무한 스크롤좀 하는 놈인가? 그럼 질수 없지
react-infinite-scroll-component
무한 스크롤을 구현하려고 여기 저기 알아보다, 해당 기능을 제공하는 라이브러리를 발견하였다. 그 용법을 알아보고, 해당 내용을 내 프로젝트에 적용시켜보자. 설치 및 임포트 과정은 간단하니 생략하겠다.
기본적인 사용법은 아래와 같다.
<InfiniteScroll
dataLength={items.length}
next={fetchData}
hasMore={true}
loader={<h4>Loading...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{items}
</InfiniteScroll>
컴포넌트이기 때문에, <InfiniteScroll />
과 같이 컴포넌트의 형식으로 사용한다. props
로 많은 속성들이 들어가는데, 하나하나 알아보자.
dataLength
데이터 배열의 길이 정보가 들어간다. 이 배열 길이 정보는 다음 번 next
함수 호출과 관련이 있다.
next
스크롤이 마지막에 닿았을 때, 데이터를 더 받아올 함수가 들어간다.
hasMore
next
함수를 더 호출할 지 말지, 그리고 endMessage를 나타낼지 말지에 대한 boolean값이 들어간다. 보통, 불러오는 데이터의 수를 제한 하기 위해 사용된다. 예로, items
의 길이를 추적하면서 특정 수를 넘겼을 시 혹은 더 이상 받아올 데이터가 없을 시, hasMore
의 값을 false로 바꾸어, 더 이상의 무한 스크롤을 멈출 수 있다.
Loader
데이터 fetch를 기다리고 있을 때, 나타날 문구가 들어간다.
endMessage
스크롤링이 끝났을 때 나타날 문구가 들어간다. hasMore
과 관련이 있다. hasMore
이 false 가 되면, endMessage
가 나타난다.
위의 용법을 사용하여 프로젝트에 적용해 보았다. 용법이 간단하여, 수월하였다.
한 가지 부분만 수정이 필요했는데, 나의 프로젝트 구조에서는 인피니티 스크롤이 적용될 컴포넌트가 한 단계 더 높은 상위 컴포넌트에서 fetch 받은 데이터를 props로 넘겨받고 있었기 때문에, next
에 담길 함수를 상위 컴포넌트에서 추가로 선언하여 props로 넘겨주어야 했다.
// 상위 컴포넌트
class Community extends React.Component {
constructor(props) {
super(props);
this.state = {
communityCards: [],
currentIndex: 0,
NUMBER_OF_ITEMS_TO_FETCH: 12, // 데이터를 한번에 12개씩만 받기로 설정한다.
};
}
componentDidMount() {
this.fetchMoreData();
}
// next에 담길 함수
fetchMoreData = () => {
fetch(`${API}/data/community/data.json`)
.then(response => response.json())
.then(result => {
const {
communityCards,
currentIndex,
NUMBER_OF_ITEMS_TO_FETCH,
} = this.state;
this.setState({
communityCards: communityCards.concat(
result.communityCards.slice(
currentIndex,
currentIndex + NUMBER_OF_ITEMS_TO_FETCH
)
),
currentIndex: currentIndex + NUMBER_OF_ITEMS_TO_FETCH,
});
});
};
render() {
return (
<CommunityCardList
fetchMoreData={this.fetchMoreData} // 해당 함수를 props로 넘긴다.
communityCards={this.state.communityCards}
/>
);
}
}
// 하위 컴포넌트
import React from "react";
import InfiniteScroll from "react-infinite-scroll-component";
import CommunityCard from "./CommunityCard";
class CommunityCardList extends React.Component {
render() {
const { communityCards } = this.props;
return (
<InfiniteScroll
dataLength={communityCards.length}
next={this.props.fetchMoreData}
hasMore={true}
>
<div className="CommunityCardGrid">
{communityCards?.map(communityCard => (
<CommunityCard communityCard={communityCard} />
))}
</div>
</InfiniteScroll>
);
}
}
코드는 위와 같이 구성된다.
결과물 또한 잘 작동한다!
어찌어찌 때려 맞춰주면 알아서 잘 돌아가주니 고맙네. 장하다 내 코드. 이 기세로 내일 필터링 기능까지 잘 돌아가주라 ^-^