개발관련/리액트
리액트 컴포넌트 무한 스크롤 구현
개발자 Dane
2023. 5. 11. 19:57
반응형
무한 스크롤 컴포넌트
import React, { useState, useEffect, useRef, FC } from "react";
interface Props {
fetchData: () => Promise<void>;
children: React.ReactNode;
}
const InfiniteScroll: FC<Props> = ({ fetchData, children }) => {
const [isLoading, setIsLoading] = useState(true);
const loader = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
setIsLoading(true);
fetchData().then((newItems) => {
setIsLoading(false);
});
}
},
{ threshold: 1 }
);
if (loader.current) {
observer.observe(loader.current);
}
return () => {
observer.disconnect();
};
}, [loader, setIsLoading, fetchData]);
return (
<div>
{children}
<div ref={loader}>
{isLoading && "로딩..."}
</div>
</div>
);
};
export default InfiniteScroll;
사용법
export const List: React.FC = () => {
const [page, setPage] = useState(1);
const [list,setList] = React.useState([])
const fetchData = async () => {
const response = await axios.get(`https://api.example.com/data?page=${page}&limit=10`);
setList(prevData => [...prevData, ...response.data]);
};
return (
<InfiniteScroll fetchData={fetchData}>
<ul>
{list.map((item,i) => (
<li key={i}>item</li>
))}
</ul>
</InfiniteScroll>
);
};
해설
- InfiniteScroll 컴포넌트를 만들어서 재사용 가능하게 합니다.
- 재사용성을 높이기 위해서 로딩 상태와 UI를 InfiniteScroll내부에 구현합니다.
- 데이터를 저장할 data 상태와 페이지 번호를 저장할 page 상태를 생성합니다.
- 페이지 번호가 변경될 때마다 API를 호출하여 데이터를 가져옵니다. 가져온 데이터는 이전 데이터와 합쳐집니다.
- Intersection Observer를 설정하여 로딩 요소가 뷰포트와 교차할 때마다 페이지 번호를 증가시킵니다.
- 로딩 요소에 ref를 설정하여 Intersection Observer가 관찰할 수 있도록 합니다.
반응형