클론프로젝트를 하면서 꼭 한번 해보고 싶었던 무한 스크롤 기능과 로딩바 기능을 구현해보았다!
스크롤을 끊임없이 감지하고 동기적으로 실행되기 때문에 메인 스레드에 영향을 준다.
실제로 스크롤 이벤트로 무한스크롤기능을 구현할때의 상황.
scroll이 맨 밑에 있을때 감지해주는 함수를 달아놨는데 스크롤이 계속 맨 밑에 머물러있을때 끊임없이 함수가 호출되고 있다.
간단히 말하자면 타겟이 화면에 노출되었는 지의 여부를 관찰할 수 있는 API
교차되었을때 실행할 callback
함수와 option
을 인자로 받는다.
const observer = new IntersectionObserver(callback, options);
타겟 엘리먼트가 교차되었을 때 실행할 함수
observer 콜백이 호출되는 상황을 조작할 수 있다.
root
rootMargin
threshold
IntersectionObserver.observe(target)
IntersectionObserver.unobserve(target)
IntersectionObserver.disconnect()
우선 target, 로딩중인지 아닌지를 판별해줄 isLoading, 현재 아이템 갯수를 나타내는 itemCount를 state로 지정해준다.
target에 변화가 있을때마다 실행해줄 useEffect에 observer 객체를 선언한다.
callback함수의 인자로 entry와 observer를 받는다. 타겟의 교차 상태를 boolean값으로 반환하는 entry.isIntersecting
가 true일때 list를 fetch하는 함수를 호출하고 itemCount에 1을 더해 setState해준다. (난 한페이지당 1개의 리스트만 호출하고 스크롤이 끝에 다다랐을때 하나씩 더 보여주는 무한스크롤을 구현예정이다.)
리스트를 fetch해오는 함수.
우선 isLoading을 true로 setState해주고, fetch를 통해 백엔드로부터 데이터를 받아온다.
setTimeout을 통해 약간의 시간차를 줘 로딩바가 더 잘보일 수 있도록 했다.
list의 갯수가 현재 itemCount와 같으면 loading이 끝난것이기 때문에 다시 false로 바꿔주었고, list를 itemCount의 수만큼 slice해 setState해주었다.
마지막으로 컴포넌트가 언마운트될때 isLoading을 false로 setState해준다.
로딩바부분.
isLoading이 true일때만 로딩바가 보여야하므로 조건부렌더링을 걸어주었고 setTarget을 forwardRef로 지정해주었다.
처음엔 그냥 ref로 지정해주었는데 에러가 나길래 리액트 공식문서를 보다가 React 컴포넌트에 ref prop을 넘겨서 그 내부에 있는 HTML 엘리먼트에 접근을 하게 해주는 forwardRef 함수를 사용하라는 답변을 보고 forwardRef를 사용했다.