Skip to content

Commit 36e38b5

Browse files
committed
Refact: isFetching과 isReachedEnd를 state가 아닌 useRef로 관리
1 parent 6a7f671 commit 36e38b5

1 file changed

Lines changed: 26 additions & 21 deletions

File tree

src/pages/Home/OOTD/index.tsx

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,35 @@ const OOTD: React.FC = () => {
1414
const [modalContent, setModalContent] = useState('알 수 없는 오류입니다.\n관리자에게 문의해 주세요.');
1515
const [isStatusModalOpen, setIsStatusModalOpen] = useState(false);
1616

17-
const [reachedEnd, setReachedEnd] = useState(false);
18-
const [isFetching, setIsFetching] = useState(false);
17+
// API 요청 중인지 확인하는 변수 (렌더링 없이 상태 관리)
18+
const isFetchingRef = useRef(false);
19+
// 모든 데이터를 불러왔는지 확인하는 변수
20+
const isReachedEndRef = useRef(false);
1921

20-
const feedPageRef = useRef(1); // 현재 페이지 번호를 참조하는 변수, 리렌더링 없이 값만 업데이트 하기 위해 상태가 아닌 useRef 사용
22+
// 현재 페이지 번호를 참조하는 변수, 리렌더링 없이 값만 업데이트하기 위해 상태가 아닌 useRef 사용
23+
const feedPageRef = useRef(1);
2124

2225
// 세션 스토리지에서 이전 스크롤 위치를 가져와 초기화
2326
const savedScrollPosition = sessionStorage.getItem('scrollPosition');
2427
const scrollPositionRef = useRef(Number(savedScrollPosition) || 0);
2528

26-
const observerRef = useRef<IntersectionObserver | null>(null); // IntersectionObserver 인스턴스를 참조하는 변수
27-
const loadMoreRef = useRef<HTMLDivElement | null>(null); // 더 많은 데이터를 로드할 때 관찰할 마지막 요소의 DOM을 참조
29+
// IntersectionObserver 인스턴스를 참조하는 변수
30+
const observerRef = useRef<IntersectionObserver | null>(null);
31+
// 더 많은 데이터를 로드할 때 관찰할 마지막 요소의 DOM을 참조
32+
const loadMoreRef = useRef<HTMLDivElement | null>(null);
2833

2934
// 전체 게시글(피드) 조회 API
3035
const getPostList = async () => {
31-
if (reachedEnd || isFetching) return;
32-
// 사용자가 스크롤을 빠르게 내리거나 ntersection Observer가 여러 번 트리거될 경우, 중복된 API 요청 발생 가능.
33-
// 이를 막기 위해 isFetching 상태를 확인하고, 현재 요청 중인 상태라면 추가 요청을 막음
36+
// 모든 데이터를 불러왔거나 요청 중이라면 함수 실행 중단
37+
if (isReachedEndRef.current || isFetchingRef.current) return;
3438

35-
setIsFetching(true);
39+
isFetchingRef.current = true; // 요청 중임을 표시
3640
try {
3741
const response = await getPostListApi(feedPageRef.current, 20);
3842

3943
if (response.isSuccess) {
4044
if (response.data.post.length === 0) {
41-
setReachedEnd(true);
45+
isReachedEndRef.current = true; // 더 이상 불러올 데이터가 없음을 표시
4246
} else {
4347
setFeeds((prevFeeds) => [...prevFeeds, ...response.data.post]);
4448
feedPageRef.current += 1;
@@ -49,28 +53,29 @@ const OOTD: React.FC = () => {
4953
setModalContent(errorMessage);
5054
setIsStatusModalOpen(true);
5155
} finally {
52-
setIsFetching(false);
56+
isFetchingRef.current = false;
5357
}
5458
};
5559

5660
useEffect(() => {
57-
if (reachedEnd && observerRef.current && loadMoreRef.current) {
58-
observerRef.current.unobserve(loadMoreRef.current);
59-
return; // 데이터의 끝에 다다르면 옵저버 해제. (더이상 피드가 없으면)
61+
if (isReachedEndRef.current && observerRef.current && loadMoreRef.current) {
62+
observerRef.current.unobserve(loadMoreRef.current); // 데이터의 끝에 다다르면 옵저버 해제 (더이상 피드가 없으면)
63+
return;
6064
}
6165

62-
observerRef.current = new IntersectionObserver( // Intersection Observer 생성
66+
// Intersection Observer 생성
67+
observerRef.current = new IntersectionObserver(
6368
debounce((entries) => {
6469
const target = entries[0];
6570
console.log('Intersection Observer:', target.isIntersecting);
66-
if (target.isIntersecting && !isFetching && !reachedEnd) {
67-
// 요소가 화면에 보이고 있고, 요청 중이 아니며며 끝에 도달하지 않았다면 api 호출
71+
if (target.isIntersecting && !isFetchingRef.current && !isReachedEndRef.current) {
72+
// 요소가 화면에 보이고 있고, 요청 중이 아니며 끝에 도달하지 않았다면 API 호출
6873
getPostList();
6974
}
70-
}, 300), // 디바운스 적용해 스크롤 이벤트 제어. 스크롤마다 이벤트 호출하는 것이 아닌 마지막 스크롤 이후 300ms동안 동작이 없으면 이벤트 호출
75+
}, 300), // 디바운스 적용, 마지막 스크롤 이후 300ms 동안 동작이 없으면 이벤트 호출
7176
{
7277
root: null,
73-
rootMargin: '100px', // // 요소가 보이기 100px 전에 미리 데이터 로드
78+
rootMargin: '100px', // 요소가 보이기 100px 전에 미리 데이터 로드
7479
threshold: 0, // 요소가 아주 조금이라도 보이면 트리거
7580
},
7681
);
@@ -80,12 +85,12 @@ const OOTD: React.FC = () => {
8085
observerRef.current.observe(loadMoreRef.current);
8186
}
8287
return () => {
83-
// 컴포넌트가 언마운트되거나 의존성이 변경될 때 옵저버 해제
88+
// 컴포넌트 언마운트 시 옵저버 해제
8489
if (observerRef.current && loadMoreRef.current) {
8590
observerRef.current.unobserve(loadMoreRef.current);
8691
}
8792
};
88-
}, [isFetching, reachedEnd]);
93+
}, []);
8994

9095
useEffect(() => {
9196
// 첫 로드 시 API 호출

0 commit comments

Comments
 (0)