스크롤 이벤트 발생시마다 eventListener를 발생시키는 것은 javascript의 main thread에 계속 성능상 영향을 줌,따라서 특정 요소가 내가 원하는 영역에 들어왔을 때만 이벤트 발생시키는 API가 필요->이걸 도와주는 게 InterSection Observer API
즉 스크롤 이벤트 발생시,계속해서 스크롤 값을 측정할 필요없이 특정 요소가 언제 viewport를 진입하고 빠져나가는지를 관찰해주는 API
Intersection Observer가 등장하기 전에는 어떤 요소가 화면에 보여지는지 감지하는 것은 매우 복잡한 일. 따라서 요소의 visibility를 감지하고 이벤트를 주는 것은 웹 사이트들을 느리게 만드는 원인 중 하나였고 따라서, Intersection 정보들이 필요하게 되었다.
우리는 언제 유저가 특정 요소에 진입하는지 확인하고 이에 따라서 포스트를(DOM) 더 불러올지 결정하는 데 사용할 것
참고 : https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
npx create-react-app infiniteScroll
<div className='loading>Loading</div>
에 붙임<div className='loading>Loading</div>
에 등록import React from 'react';
import InfiniteScroll from './InfiniteScroll';
function App() {
return (
<div className="App">
<h2 style={{textAlign:'center'}}>InfiniteScroll Practice</h2>
<InfiniteScroll />
</div>
);
}
export default App;
import React,{useState,useEffect,useRef} from 'react'
const postStyle = {
color: 'blue',
height: '200px',
textAlign: 'center',
padding: '5px 10px',
background: 'pink',
marginTop: '15px',
display:'flex',
justifyContent:'center',
alignItems:'center'
};
const containerStyle = {
maxWidth: '760px',
margin: '0 auto'
}
function InfiniteScroll() {
const [postList,setPostList] = useState({
list :[1,2,3,4]
})
//tracking on Which page we currently are
const [page,setPage] = useState(1);
//referencing loader
const loader = useRef(null);
useEffect(()=>{
const option = {
root : null,
rootMargin : '20px',
threshold:0
}
//컴포넌트 렌더링 완료시,initialize IntersectionObserver and attaching to Load More div
const observer = new IntersectionObserver(handleObserver,option);
if (loader.current) {
observer.observe(loader.current)
}
},[]);
useEffect(()=>{
//현재 page변할 때마다 실행하는 useEffect
let addList = ['a','b','c','d'];
const newList = setPostList({list : [...postList.list,...addList]});
},[page])
// 유저의 스크롤이 Load More div에 intersection(진입시) 무엇이 일어날지 다룸
// 즉, 페이지 변수를 업데이트
const handleObserver = (targetList)=>{
const target = targetList[0];
if (target.isIntersecting) {
setPage(page=>page+1);
}
}
const renderCard = postList.list.map((post,index)=>(
<div key={index} className='post' style={postStyle}>
<h2>{post}</h2>
</div>
))
return (
<div className='container' style={containerStyle}>
<div className='post-list'>
{renderCard}
<div className='loading' ref={loader}>
<h2>Load More</h2>
</div>
</div>
</div>
)
}
export default InfiniteScroll
https://github.com/superfly9/react-infinite-scroll
참고: https://dev.to/hunterjsbit/react-infinite-scroll-in-few-lines-588f