[React] 현재 스크롤 위치 감지해서 무한스크롤 구현하기 (infiniteScroll)
infiniteScroll / scrollHeight / scrollTop / clientHeight


무한스크롤 의 구현방식은 여러가지 입니다
(infinite-scroll-component / intersection-observer / 스크롤 위치 감지 등)
저는 스크롤 위치가 ‘scrollHeight’ 의 맨 끝 지점(100) 에 왔을때
서버에서 데이터를 10개씩 추가로 불러오는 방식을 구현해봤습니다
1. 서버에서 데이터 받아오기

1-1. fetch 또는 Axios 를 이용하여 서버에서 데이터를 받아오고
1-2. useState 빈배열을 ‘두개 생성’ 합니다
1-3. 배열 하나는 데이터를 보여주고
1-4. 배열 하나는 남은 데이터를 저장하는 용도입니다
2. 저장소에서 데이터 꺼내오기

👆 스크롤이 목표위치 에 도달했을때 서버에서 데이터를 추가로 받아오는 함수
2-1. 저장된 데이터가 0개 가 아닐경우 실행
2-2. 배열에 담긴 값을 10개씩 꺼내서 출력 (몇개씩 출력할지는 셋팅)
3. 스크롤 위치 감지


👆 스크롤의 위치를 감지하고 조건에 만족하면 데이터를 꺼내오는 함수를 실행
⭐ scrollTop + clientHeight >= scrollHeight
4. 스크롤 이벤트 등록 & 삭제

스크롤 위치를 감지할때마다 이벤트를 실행하고 & 삭제
addEventListener / removeEventListener
5. 무한스크롤 구현

10개씩 데이터를 불러오는 무한스크롤
무한스크롤 구현에 성공한 코드 👇
const [poolList, setPoolList] = useState([]);
const [savePoolList, setSavePoolList] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const poolData = () => {
setIsLoading(true); // 데이터를 불러오는중에는 로딩중 표시
fetch(
"https://gateway.pinata.cloud/ipfs/QmNYomgBofjWrYkkdWQA2KTqkv8HxMe3iwFsYScGCkX16K"
)
.then((res) => res.json())
.then((list) => {
setPoolList(list.slice(0, 10)); // 서버에서 데이터를 10개만 보여주고
setSavePoolList(list.slice(10)); // 보여주는 데이터 10개 제외한 나머지는 빈배열에 저장
setIsLoading(false); // 데이터를 다 불러왔으면 로딩중 끝
});
};
poolData();
}, []);
const poolSaveData = async () => {
// 서버에서 데이터를 추가로 받아오는 함수 (비동기처리)
if (savePoolList.length !== 0) {
// useState 배열에 저장된 길이가 0이 아닐경우 실행
setIsLoading(true); // 데이터를 불러오는중에는 로딩중 표시
setTimeout(() => {
// 바로 실행하지말고 1초 뒤에 실행시키기
setPoolList([...poolList, ...savePoolList.slice(0, 10)]);
// 서버에 담긴 값, 저장된 데이터 10개 꺼내기
setSavePoolList(savePoolList.slice(10)); // 저장된 데이터 10개 출력
setIsLoading(false); // 데이터를 다 불러왔으면 로딩중 끝
}, 1000); // 👉 1초
}
};
const infiniteScroll = useCallback(() => {
//스크롤 높이를 감지해서 👉 조건에 만족하면 poolSaveData 함수 호출
let scrollHeight = Math.max(
document.documentElement.scrollHeight,
document.body.scrollHeight
);
let scrollTop = Math.max(
document.documentElement.scrollTop,
document.body.scrollTop
);
let clientHeight = document.documentElement.clientHeight;
scrollHeight -= 100; // 스크롤이 맨 끝 지점(100)에 왔을때
if (scrollTop + clientHeight >= scrollHeight && isLoading === false) {
poolSaveData();
}
}, [isLoading]);
useEffect(() => {
window.addEventListener("scroll", infiniteScroll, true); // 스크롤 이벤트 등록
return () => window.removeEventListener("scroll", infiniteScroll, true); //스크롤 이벤트 삭제
}, [infiniteScroll]);