인스타그램 피드들을 감싼 Feeds 컴포넌트 최하단에 intersectionObserver를 관리하는 LoadMoreFeed 컴포넌트를 만들어주었다.
import React, { useEffect, useRef, useState } from 'react';
import Feed from '../Feed/Feed';
import './Feeds.scss';
import Skeleton from '../Skeleton/Skeleton';
import LoadMoreFeed from '../LoadMoreFeed/LoadMoreFeed';
function Feeds() {
const [page, setPage] = useState(0);
const [feedList, setFeedList] = useState([]);
const [isLoading, setIsLoading] = useState(false);
return (
<div className="feeds-gayun">
<div className="feed-container">
{page === 0 && isLoading
? createSkeletonFeed(SKELETON_FEED_COUNT)
: feedList.map((feed, idx) => <Feed key={idx} feed={feed} />)}
</div>
<LoadMoreFeed isLoading={page !== 0 && isLoading} setPage={setPage} />
</div>
);
}
export default Feeds;
LoadMoreFeed에서는 최초 렌더링 시에 observer를 생성하고, 관찰을 시작한다.
import React, { useRef } from 'react';
import { useEffect } from 'react/cjs/react.development';
import './LoadMoreFeed.scss';
function LoadMoreFeed({ isLoading, setPage }) {
const feedEndRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(entry => {
if (entry[0].isIntersecting && entry[0].intersectionRatio > 0.1) {
setPage(page => page + 1);
}
});
observer.observe(feedEndRef.current);
return () => {
observer.unobserve(feedEndRef.current);
};
}, []);
return (
<div className="feed-end" ref={feedEndRef}>
{isLoading ? <div className="loading" /> : ''}
</div>
);
}
export default LoadMoreFeed;
아직 고민이 필요한 부분