포켓몬 API를 활용하여 도감 만들기
API 요청
- 포켓몬 API는 내부에 데이터가 복잡한 것 같다.
- axsios.all을 사용하여 가져온 150개에 대에터에 병렬요청을 하였다.
- 이 복잡한 데이터를 내가 원하는 것만 가져오기 위해서 map(), find()로 원하는 데이터만 가져왔다.
연결
- 데이터를 무한 스크롤을 사용하여 연결을 해주었다.
useInfiniteQuery
- 쿼리를 사용하여 무한 스크롤을 쉽게 구현할 수 있다.
- data에는 모든 불러온 데이터를 담은 객체를
- fetchNextPage()는 다음 페이지 데이터를 불러오는 함수이다.
- hasNextPage는 다음 페이지가 있다면 boolean 값으로 리턴 한다. 있다면 true를 반환
- isFetching 현재 데이터를 가져오고 있는 중인가? boolean
- isFetchingNextPage 다음 페이지 데이터를 가죠오는 중인지 여부 boolean
- isLoading 초기 데이터 로딩 중 여부 boolean
- isError API 요청 실패 여부 boolean
- error 오류 발생 시 오류 객체 boolean
const { data, fetchNextPage, hasNextPage, isLoading, isError } =
useInfiniteQuery({
queryKey: ['pokemon-species'],
queryFn: ({ pageParam = 0 }) => getPokemon(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => {
return lastPage?.nextPage ?? undefined;
},
});
IntersectionObserver
- 사용자가 스크롤을 내릴 떄 자동으로 fetchNextPage()는 실행한다.
- 특정 요소가 뷰포트(화면)에 나타나는지 감지하는 API이다.
- entries[0].isIntersecting === true 일 떄, 요소가 화면에 나타내는지를 의미하고 이를 활용하여 스크롤이 끝에 도달할 떄 자동으로 다음 데이터를 로드 한다.
- observer.observe(element)를 호출하면 엘리먼트의 가시성을 감시, observerRef.curren 무한 스크롤을 감지할 대상 요소를 선택한다. ref로
- 컴포넌트가 언마운트되거나 useEffect가 재실행될 떄 기존 observer를 제거하여 메뮈 누수를 방지 한다.
- unobserve()를 호출하면 해당 요소의 감시가 중단
- { threshold: 1.0 } 요소가 화면에 어느 정도 보여야 실행 되는가?
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasNextPage) {
fetchNextPage();
}
},
{ threshold: 0.5 },
);
if (observerRef.current) {
observer.observe(observerRef.current);
}
return () => {
if (observerRef.current) {
observer.unobserve(observerRef.current);
}
};
}, [fetchNextPage, hasNextPage]);
🛠 React Query 인피니트 스크롤에서 무한 로딩 발생
- React Query의
useInfiniteQuery
를 활용하여 무한 스크롤을 구현했다. - 그런데 화면에서 계속 스피너(로딩 화면)만 보이고, 데이터가 나오지 않는 문제가 발생했다.
🔍 원인 분석
isLoading
을useInfiniteQuery
에서 제공하는 것이 아니라 내가 기존에 만들었던 state를 사용하고 있었다.isLoading
을 따로 관리하는useState
를 만들어서 데이터 로드 완료 후에도 true 상태로 남아있었다.
🚀 해결 방법
- 기존
useState
를 삭제하고, React Query의isLoading
을 직접 사용했다. - 코드 변경 전:
const [loading, setLoading] = useState(true); if (loading) return <Loading loading={loading} />;
🎯 배운 점
- React Query는 자체적으로 로딩 상태(isLoading)를 관리하므로, 별도의 state를 만들 필요가 없다.
- 잘못된 state 관리는 무한 로딩 같은 예기치 않은 버그를 발생시킬 수 있다.
- useState로 상태를 추가하기 전에 React Query가 제공하는 상태값을 먼저 확인하자!
지금까지 만든 화면
'리액트' 카테고리의 다른 글
포켓몬 API 활용한 포켓몬 도감 토이 프로젝트에 대한 회고 (0) | 2025.02.09 |
---|---|
포켓몬 API 토이 프로젝트를 하면서 문제점 (0) | 2025.02.08 |
React (0) | 2025.01.07 |
React-player 라이브러리 (0) | 2024.12.31 |
React Potal Modal 구현하기 (2) | 2024.12.31 |