일단 무한스크롤을 구현하려면 스크롤이 특정 부분에 닿았을 때 특정 함수를 실행하기 위해
react-intersection-observer
와 같은 라이브러리를 설치하자.
yarn add react-intersection-observer
intersection-observer
에 대한 설명은 블로그 참고-⭐️
장소 검색 페이지 부분을 무한스크롤로 구현해야 하는데,,
처음에 리액트 쿼리의 useInfiniteQuery 를 사용하여 구현해보려 하였으나 실패.
왜나하면 우리는 약 12000개의 장소 정보가 supabase의 places 테이블에 저장되어 있어서
useInfiniteQuery의 getNextPageParam 함수 부분을 작성하는게 난감했다.
const { data, error } = await supabase
.from('places')
.select('*')
.ilike('place_name', `%${searchValue}%`)
.range((currentPage - 1) * pageSize, currentPage * pageSize - 1);
이런식으로 range
메서드를 통해 pageSize 만큼 끊어서 가져올건데,
이를 통해 반환되는 data에는 total_page 라던가, lastPage 와 같은 정보가 들어있지 않다.
그래서 useInfiniteQuery 사용을 포기하고
다른 방식으로 구현해보려고 시도했다.
useEffect(() => {
// 새로운 검색어가 입력될 때 기존에 검색된 장소를 비움
setSearchedPlaces([]);
setCurrentPage(1);
}, [searchValue]);
const loadMoreData = async () => {
setLoading(true);
try {
const { data, error } = await supabase
.from('places')
.select('*')
.ilike('place_name', `%${searchValue}%`)
.range((currentPage - 1) * pageSize, currentPage * pageSize - 1);
if (error) {
console.error('데이터 가져오기 에러:', error.message);
} else {
if (data.length === 0) {
return;
}
console.log('페이징 및 필터링된 데이터:', data);
setSearchedPlaces([...searchedPlaces, ...data]); // 기존 데이터와 새로운 데이터 병합
setCurrentPage((prev) => prev + 1); // 다음 페이지로 이동
}
} finally {
setLoading(false);
}
};
더 리팩토링을 할거지만, loadMoreData
라는 함수를 다음과 같이 작성하였다.
그리고
const { ref } = useInView({
threshold: 1,
onChange: (inView) => {
if (!inView) return;
loadMoreData();
},
});
이 부분을 추가하여 무한스크롤을 구현해보았다.
<div
style={{
textAlign: 'center',
backgroundColor: 'green',
color: 'white',
width: '100%',
height: 50,
}}
ref={ref}
>
Trigger to Fetch Here
</div>
Trigger to Fetch Here
부분에 닿으면 새로운 데이터 20개를 가져온다.
아직 수정해야 할 부분이 많지만......
오늘 처음 무한스크롤에 도전해보고 성공했다는 것에 의의를 둔다..
아직 UI는 못생긴 상태ㅎㅎ
갈길이 멀다!!! 🏃♀️🏃♂️