(코드 작성하면서 바로바로 기록하기 위해 설명하는투가 아니라 간략하게 작성)
const target = useRef<HTMLDivElement>(null);
...
<div ref={target}></div>
코드를 짰을 때, console.log(target.current)로 확인하니 현재 ref가 target으로 설정되어 있는 요소를 가져옴.
const target = useRef<HTMLDivElement | null>(null);
// console.log(target.current); // <div></div>
useEffect(() => {
if(target.current){
return observer.observe(target.current);
}
}, []);
const options = {
threshold: 1.0,
};
const callback = () => {
if(target.current){
// target.current.innerText = '관측 중';
console.log(page);
setPage((prev) => prev + 1);
}
};
const observer = new IntersectionObserver(callback, options);
위의 코드를 브라우저에서 뷰포트에 들어왔는지 아닌지 추적을 못하는 상황
원인: 콜백함수에 전달되는 첫 번째 인자 entries 정보가 담겨있지 않음.
const callback = (entries: IntersectionObserverEntry[]) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is intersecting:', entry.target);
// 페이지 업데이트 등 원하는 동작 수행
setPage((prev) => prev + 1);
// 교차 영역 관찰 중단
// observer.unobserve(entry.target);
}
});
};
entries인자 추가
브라우저 새로고침 시에는 추적이 안되고 브라우저 켜놓은 상태에서 vscode 저장을 해야 추적이 되는 요상한 상황 발생.
콜백 함수 내에서 state 갱신함수를 쓰고 동시에 console.log() 로 확인하려고 하니까 비동기처리 때문에 바로 확인하지 못함. useEffect 를 사용하여 isEightUnder 가 변화할 때 마다 isEightUnder 값을 확인하니까 제때 잘 변경된 것을 확인함.
무한스크롤에 필요한 모든 함수를 callback에 넣어서 가져오려고 하니까 비동기 때문에 제대로 작동을 안함.
그래서 callback에는 뷰포트에 타겟이 추적되면 페이지 증가시키는 상태 갱신 함수만 넣어둠.
그리고 useEffect로 페이지 변화가 감지될 때마다 새로운 페이지의 get 요청을 불러오는 코드를 작성함.
제대로 가져오는 것처럼 보이나 콘솔 창에는 이미 불러온 데이터가 또 불러오는 지 부딪히는 경고창 뜸.
const target = useRef<HTMLDivElement | null>(null);
const pageRef = useRef(page);
useEffect(() => {
if(target.current){
return observer.observe(target.current);
}
}, []);
const options = {
threshold: 1.0,
};
// 이전 데이터가 8개 미만인지 상태
const [isEightUnder, setIsEightUnder] = useState(false);
useEffect(() => {
if(isEightUnder){
return;
};
// console.log(page); // page 증가되는 것 확인
const showPageCommu = async () => {
try {
const response = await axios.get(`https://api.portfolly.site/boards/pages?division=${division}&page=${page}&size=${size}`);
const currentData = response.data.data;
console.log(currentData);
console.log(currentData.length < 8);
setIsEightUnder(currentData.length < 8); // 값 변경
setData([...data, ...currentData]);
} catch (error) {
console.error('Error fetching data:', error);
}
};
showPageCommu();
}, [page]);
// 콜백 함수에는 뷰포트에 타겟이 닿으면 페이지만 증가시키는 함수 넣기
// 콜백 함수 위에 UseEffect로 page 변경이 감지되면 실행시키는 함수
// 그 함수안에는 바뀐 페이지로 get 요청 보내오고
// 받은 데이터 개수가 8개 미만이면 IsEightUnder 상태 바꾸기
// 다음 페이지 요청이 와도 isEightUnder 가 true 면 바로 리턴 때리기
const callback = (entries: IntersectionObserverEntry[]) => {
entries.forEach(async entry => {
// console.log(entry.isIntersecting); // boolean 값으로 나옴 추적중이면 true 아니면 false
if (entry.isIntersecting) {
console.log('Element is intersecting:', entry.target);
setPage(prev => prev + 1);
// const currentPage = pageRef.current; // 현재 페이지 값을 캡처
}
});
};
초기에 1페이지를 렌더링하는 것과 intersection observer로 가져오는 페이지의 데이터가 부딪히는 것으로 확인.
원인 : 초기렌더링의 1페이지가 observer 콜백 함수를 호출할 때도 갱신되지 않고 남아있는 것으로 보임.
...
if(page > 1){
showPageCommu();
};
...
으로 변경해보았으나 페이지 변경은 확인되는데 실제 페이지에 해당하는 데이터 값을 불러오지 않음.
const target = useRef<HTMLDivElement | null>(null);
const [isEightUnder, setIsEightUnder] = useState(false); // 이전 데이터가 8개 미만인지 상태
// const [isLoading, setIsLoading] = useState(false); // 뷰포트에 타겟이 왔는지 아닌지
// console.log(isLoading);
useEffect(() => {
const showPageCommu = async () => {
try {
const response = await axios.get(`https://api.portfolly.site/boards/pages?division=${division}&page=${page}&size=${size}`);
const currentData = response.data.data;
console.log(currentData);
setData([...data, ...currentData]);
if (currentData.length < 8) {
setIsEightUnder(true);
// observer.unobserve(target.current); // Intersection Observer 중지
return;
}
} catch (error) {
console.error('Error fetching data:', error);
}
};
if(page > 1){
showPageCommu();
}
}, [page]);
// 페이지 바뀌면 실행시켜~ 페이지는 콜백함수로 바꿀거야~
useEffect(() => {
if(target.current){
observer.observe(target.current);
}
return () => {
if (target.current) {
observer.unobserve(target.current);
}
};
}, []);
const options = {
threshold: 1.0,
};
// 지금 뷰포트에 들어왔는지 아닌지 분간하는 state 만들어보자
const callback = (entries: IntersectionObserverEntry[]) => {
entries.forEach(async entry => {
if (entry.isIntersecting) {
// setIsLoading(entry.isIntersecting);
if(isEightUnder){
console.log('stop');
return;
}
console.log('Element is intersecting:', entry.target);
setPage((prev) => prev + 1);
}
});
};
const observer = new IntersectionObserver(callback, options);
코드 순서 바꾸고 몇 가지 수정해주니까 페이지 별로 데이터 잘 불러오는 것 확인함.
그래도 여전히 초기렌더링 단계에서 observer 인식을 못하는 문제 있음.
정보에 감사드립니다.