- 사용자가 스크롤 할 때마다 새로운 데이터를 가져온다
- 모든 데이터를 한 번에 가져오는 것보다 효율적
ex. 트위터
- 언제 새로운 데이터를 가져오는가?
- 사용자가 버튼을 눌렀을 때
- 페이지의 특정 지점을 스크롤 했을 때
useInfiniteQuery
- 페이지네이션과는 다른 api 사용
- 페이지네이션
- 현재 페이지를 컴포넌트 상태에서 추적
- 사용자가 새 페이지를 열기 위해 버튼을 클릭했을 때, 업데이트 된 상태가 쿼리 키를 업데이트하고 쿼리 키가 데이터를 업데이트 하는 방식
- useInfiniteQuery
- 다음 쿼리가 무엇인지 추적함
- 다음 쿼리가 데이터의 일부로 반환
- 사용할 api에서는 result 라는 데이터 배열을 가진 객체를 프로퍼티로 갖는다.
- 또한, api에서는 다음에 사용할 쿼리와 이전 쿼리, 총 페이지 수를 알려준다.
useQuery vs useInfiniteQuery
- 반환된 데이터의 형태가 다르다.
- useQuery : 단순히 쿼리 함수에서 반환되는 데이터 형태
- useInfiniteQuery : 두 개의 프로퍼티를 갖는다
1) pages : 배열 형태
: 페이지에 있는 각 요소가 useQuery에서의 데이터와 같은 형태
2) pageParams
: 각 페이지의 매개변수 기록 (많이 사용되는 편은 아니다!)
: 모든 쿼리는 페이지 배열에 고유한 요소를 가지고 있고 그 요소는 해당 쿼리에 대한 데이터에 해당한다 => 페이지가 진행되며 쿼리도 변경됨
: pageParams는 검색된 쿼리의 키를 추적
- 구문이 다르다.
- pageParams : 쿼리 함수에 전달되는 매게 변수
useInfiniteQuert("sw-people(쿼리 키)", ({ pageParam =
defalutUrl (첫번째로 정의한 Url을 기본값으로 사용) }) => fetchUrl(pageParma)
- React-Query가 pageParam의 현재 값을 유지
- 컴포넌트 상태 값의 일부 XX
- useInfiniteQuery에 옵션을 사용
- getNextPageParam : (lastPage, allPages) >> 다음페이지로
- 반환 객체의 특수한 프로퍼티
- fetchNextPage : 사용자가 더 많은 데이터를 요청할 때 호출
ex. 더 많은 데이터가 필요하여 버튼을 누를 때 / 스크린에서 데이터가 소진되는 지점을 누를 때
- hasNextPage : getNextPageParam의 반환 값을 기반으로 하는 함수
- 이 프로퍼티를 useInfiniteQuery에 전달하여 마지막 쿼리의 데이터를 어떻게 사용할 것인지 지정
- undefined 인 경우 => 더 이상 데이터 없음
- useInfiniteQuery에서 반환 객체와 함께 반환 된 경우 hasNextPage는 거짓
- isFetchingNextPage : 다음 페이지를 가져오는 지 ? 아니면 일반적인 페칭인지 구별 가능
Flow
- 컴포넌트가 마운트 되다
- 이 시점에서 useInfiniteScroll이 반환된 객체의 data : undefined
프로퍼티가 정의되어 있지 않다. (쿼리를 만들지 않았기 때문에)
- useInfiniteScroll이 쿼리 함수를 사용하여 1페이지를 가져온다
- 쿼리 함수는 useInfiniteScroll의 첫 번째 인수
그리고 pageParam을 인수로 받음
첫 pageParam은 우리가 기본 값으로 정의한 것이 지정
-
pageParam을 사용하여 첫 번째 페이지를 가져오고 반환 객체 데이터의 페이지 프로퍼티를 설정한다.
=> 인덱스가 0인 배열의 첫 번째 요소 설정
=> { .. } 쿼리 함수가 반환 하는 값
-
데이터가 반환된 후 react-query가 getNextPageParam (useInfiniteScroll의 옵션)을 실행
=> lastPage, allPages를 사용해서 받아온 내용을 바탕으로,
pageParam을 업데이트 => 다음페이지 링크가 업데이트 된다
-
다음 페이지?
hasNextPage 값을 정의하는 방식 => pageParam이 정의되어있는가 여부
-
다음페이가 있는 상태에서
1) 다음페이지 버튼 누르기 2) 스크롤 하기 등을 통해 fetchNextPage 함수를 호출 할 때, useQuery가 useInfiniteScroll을 실행한다
-
이를 사용해서 또 다음 요소를 업데이트하거나, 데이터의 프로퍼티인 페이지 배열에 다음 요소를 추가
-
새 데이터를 가지고 getNextPageParam 실행하여 NextPageParam을 설정
-
더이상 페이지가 없다면?
pageParam : undefined
-
hasNextPage 도 거짓이 된다 => 작업 완료, 더이상 데이터 없음
사용하기
페칭과 에러
- useQuery 처럼 isLoading 사용하기 => 캐시된 데이터가 없을 때의 데이터 정의
- isError, error => 에러 발생 시 화면 정의
- 더이상 에러가 발생하지 않는다 ㅎㅎ
- 그런데 정해진 위치에 도달해서 새로 데이터를 가져 올 때 사용자에게 피드백을 주지 않는다 => 데이터 수집하는 피드백을 줘보자.
isLoading 을 isFetching 으로 바꾼다면?
- 최초 데이터 패칭은 잘 되지만, 새로운 페이지가 열릴 경우 스크롤이 위로 돌아간다
- 왜? 데이터는 더 있지만 새로운 페이지가 열릴 때마다 바로 조기 retrun 이 되어버리기 때문이다.
isLoading과 isFetching 을 함께 사용하기
- loading 중 일 때,
- isFetching 중 일때를 각각 지정해준다.
- 스크롤도 끊기지 않고, 데이터를 새로 가져오는 것도 보인다.
- 데이터의 중간부터 시작할 때 유용 (시작점 + 이전 데이터 + 이후 데이터)
- next 메서드처럼 previous 메서드도 존재
- 둘 다 수행하면 양방향 스크롤이 가능함