React
[React] 리액트 무한스크롤 예제 및 동작 과정 설명
solfa
2024. 5. 27. 03:21
const observer = useRef();
...
const lastMovieElementRef = useCallback(
(node) => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
setPage((prevPage) => prevPage + 1);
}
});
if (node) observer.current.observe(node);
},
[hasMore]
);
동작 과정
- useCallback 설정: lastMovieElementRef는 useCallback 훅을 사용하여 정의된다. 이는 함수가 재생성되지 않고 메모이제이션되어 성능을 최적화한다. useCallback의 의존성 배열에 hasMore를 포함시켜 hasMore이 변경될 때만 함수가 재생성된다.
- node의 역할:
- 초기화: 컴포넌트가 처음 렌더링될 때 node는 null이다.
- 노드 할당: 특정 DOM 요소가 렌더링되고 ref가 할당될 때 node는 해당 DOM 요소를 가리키게 된다. 이 DOM 요소가 뷰포트에 들어올 때 Observer가 트리거된다.
- Intersection Observer 설정:
- 기존 Observer 정리: observer.current.disconnect()를 호출하여 기존의 Intersection Observer 인스턴스를 정리한다. 이는 메모리 누수를 방지한다.
- 새 Observer 생성: new IntersectionObserver를 사용하여 새로운 Intersection Observer 인스턴스를 생성하고 observer.current에 저장한다. 이 Observer는 entries 배열을 통해 관찰된 요소들의 가시성을 추적한다.
- Observer 연결:
- 노드 관찰: if (node) observer.current.observe(node); 부분에서 node가 유효한 DOM 요소일 경우, 새로 생성된 Observer 인스턴스가 이 요소를 관찰하도록 설정한다. 이때 node는 ref를 통해 전달된 실제 DOM 요소를 참조한다.
- ref 속성: 마지막 요소(movies.length === index + 1)에 lastMovieElementRef를 설정하여 해당 요소가 뷰포트에 들어오면 페이지를 증가시키도록 한다.
- 노드 관찰: if (node) observer.current.observe(node); 부분에서 node가 유효한 DOM 요소일 경우, 새로 생성된 Observer 인스턴스가 이 요소를 관찰하도록 설정한다. 이때 node는 ref를 통해 전달된 실제 DOM 요소를 참조한다.
이후 렌더링할 때
return (
<Center>
{movies.map((movie, index) => (
<MovieWrapper
key={`${movie.id}-${index}`}
onClick={() => handleImageClick(movie.id)}
ref={movies.length === index + 1 ? lastMovieElementRef : null}
>
<Poster
src={`https://image.tmdb.org/t/p/w200${movie.poster_path}`}
alt={`Movie Poster ${movie.title}`}
/>
<div>
<Title>{movie.title}</Title>
<Star>{movie.vote_average}</Star>
<Overview>
<p>{movie.overview}</p>
</Overview>
</div>
</MovieWrapper>
))}
</Center>
);
wrapper처럼 특정 요소에 할당하면 된다!
movies.length === index + 1: 현재 요소가 마지막 요소인지를 확인,
마지막 요소가 화면에 나타날 때만 Intersection Observer가 작동하게 하면서 스크롤을 계속 가능하게 하는 것~~
728x90