하지만 날로 먹지 못했다. 몇 시간의 삽질 끝에야 먹었다.
공식 문서를 잘 읽자...
window객체는 클라이언트 사이드 측 렌더링이 진행될 때 만들어지기 때문에!!
서버사이드 렌더링을 우선하는 nextjs에서는 window에 접근하지 못했던 것...
접근방법은 두 가지였고, 아래 각각의 이유로 window 직접 접근을 포기했다.
if(window) {
//1.if문으로 존재 체크 후 window에 접근하기
//하지만 스크롤 체크가 window생성 이후 진행된다는 보장이 없다!
//스크롤 체크만을 위해 async/await을 쓰는 것도 지나치다!
}
useEffect(()=>{
//2.클라이언트 사이드에서의 진행이 보장되는 useEffect안에서 접근
}, [
//뭘 보고...체크할 건데요?
]);
노마드코더 수업때 쓰던 방법.
window의 스크롤에 직접 접근하는 방법 대신 두 번째로 택한 것이 노마드코더 수업 때 사용했던 framer-motion이었다.
단, 그때와는 버전 차이로 인해 직접 문서를 읽으면서 적용했다.
const { scrollY } = useScroll();
const [scroll, setScroll] = useState(null);
useEffect(() => {
return scrollY.onChange((latest) => {
setScroll(latest);
})
}, []);
우리가 원하는 건 scroll이 바닥을 찍었느냐 아니냐일 뿐이지, 상세한 스크롤 값은 필요가 없는데....
좀 더 효율적인 방식이 있을 것 같아 다른 방법을 찾아보았다.
entries를 잘 써야 했습니다!!
공식 문서 번역이 이해가 안 되어서 잘 해석해 둔 블로그 글을 가져왔다.
https://heropy.blog/2019/10/27/intersection-observer/https://velog.io/@silverj-kim/무한스크롤-intersection-observer
공식문서의 예시와 위 블로그에서 번역한 옵션들을 사용하여… 드디어 인식에 성공했다.
infinite query와 조합하여 사용했다.
const {
data: StoreQueryDatas,
fetchNextPage,
hasNextPage,
isFetching: StoreQueryFetching,
isLoading: StoreQueryLoading,
} = useInfiniteQuery({
queryKey: ["store", nowCategory],
queryFn: ({ pageParam = 1 }) =>
fetchStoresData({ nowCategory: nowCategory, page: pageParam }),
getNextPageParam: (NowPage, pages) => {
console.log("다음페이지:", NowPage.currentPage + 1);
if (NowPage.next) return NowPage.currentPage + 1;
else return null;
},
retry: 0,
refetchOnWindowFocus: false,
});
const storeRef = useRef(null);
let io = null;
const [throttle, setThrottle] = useState(true);
const throttling = () => {
console.log("스크롤 콕", throttle);
if (throttle) {
setThrottle(false);
setTimeout(() => {
console.log("새 정보");
fetchNextPage();
}, 100);
setThrottle(true);
}
};
useEffect(() => {
io = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) throttling();
});
});
io.observe(storeRef.current);
}, [StoreQueryDatas]);
😌 디바운싱보다 쓰로틀링
처음엔 당연히 여러 번 찍는 것중 한 번만 인식해야 하니 디바운싱이겠지?했는데...
디바운싱보다 쓰로틀링 쪽이 좀 더 자연스러운 무한 스크롤 진행이 가능하다고 한다!
해당 방식을 이용하여 무한 스크롤을 적용할 수 있었으나..
....길다! 코드가 지나치게 길다.
쓰로틀링을 아예 사용하지 않는 방법도 있지 않을까? 하고 찾아본 결과.
react측에서 observer를 이용하여 만든 훅이 있다고 한다! 즉시 사용했다.
사용 동작원리는 observer와 크게 다르지 않았다.
거기에 현재 무한 스크롤링과 함께 사용중인 인피니트 쿼리를 도입하여 함께 사용했다.
const { data, fetchNextPage, isFetchingNextPage, isLoading } =
useInfiniteQuery({
queryKey: "bamboo",
queryFn: ({ pageParam = 1 }) => fetchBambooList(pageParam),
getNextPageParam: NowPage => {
if (NowPage.next) return NowPage.currentPage + 1;
},
retry: 0,
refetchOnWindowFocus: false,
});
const [ref, inView] = useInView();
useEffect(() => {
if (inView) fetchNextPage();
}, [inView]);