const targetRef = useRef<HTMLDivElement>(null);
: useRef 를 사용하여 DOM에 접근하여 직접 조작할 수 있도록 한다. axios({ baseURL: API_HOST, url: `/recentPosts/${loadPostCount.current}` })
client 에서 요청 횟수 (lodePostCount
) 라는 변수를 url 경로에 담아
req.params
API를 이용해 loadPostCount
라는 파라미터를 받아오도록 구현했다.req.params
는 라우팅 시 /:key
형식으로 지정이 가능하다. /recentPosts?loadPostCount=${loadPostCount.current}
req.param('loadPostCount')
async/await
를 사용하였다.async/await
를 사용하지 않으면 쿼리를 날리면서 데이터를 다 안받아왔지만 다음 라인으로 넘어가버리기 때문에, 위 코드의 line 8 에서 posts 변수가 undefined이게 된다. const RecentPostsPage = () => {
const [posts, setPosts] = useState<PartialPost[]>();
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isDone, setIsDone] = useState<boolean>(false);
const targetRef = useRef<HTMLDivElement>(null);
const loadPostCount = useRef<number>(0);
const loadPosts = () => {
setIsLoading(true);
axios({ baseURL: API_HOST, url: `/recentPosts/${loadPostCount.current}` })
.then(response => {
if (Array.isArray(response.data) && !response.data.length) {
setIsLoading(false);
setIsDone(true);
return;
}
if (response.data.length) {
setPosts(prev => (prev ? [...prev, ...response.data] : response.data));
loadPostCount.current += 1;
}
setIsLoading(false);
})
.catch(error => {
console.error(error);
});
};
useEffect(() => {
loadPosts();
}, []);
const onIntersect = useCallback(
([entry]: IntersectionObserverEntry[]) => {
if (!entry.isIntersecting || isDone) {
return;
}
loadPosts();
},
[isDone]
);
useEffect(() => {
if (!targetRef.current) {
return;
}
const observer = new IntersectionObserver(onIntersect, {
threshold: 0.4,
});
observer.observe(targetRef.current);
return () => observer && observer.disconnect();
}, [isLoading, onIntersect]);
return (
<>
<div> 최신 글 페이지 입니다.</div>
<PostCardGrid posts={posts} />
{isLoading && !isDone && <PostCardGridSkeleton />}
{!isLoading && (
<div
ref={targetRef}
style={{
width: '100%',
height: '5rem',
}}
/>
)}
</>
);
};
export default RecentPostsPage;