무한스크롤 기능을 구현하면서 문제가 있었던 부분을 남겨보려고 한다.
우선 tanstack-query 공식문서에서 설명하는 useInfiniteQuery의 사용법은 위와 같다.
그리고 나서 내가 구현하려고 했던 코드를 적어보면 아래와 같다.
export const productQuery = {
useGets : function() {
return useInfiniteQuery<IProductPublicFindListResponse<IApiResponse[]>, Error>({
queryKey: ["products"],
queryFn: ({ pageParam = 1 }) => productApi.gets(String(pageParam)),
getNextPageParam: (lastPage) => {
const currentPage = lastPage.meta.currentPage;
const totalPage = lastPage.meta.totalPage;
return currentPage! < totalPage! ? currentPage! + 1 : undefined;
},
}
}
위의 코드를 보면 공식문서에서 제공한대로 사용했다라고 생각해서 오류가 안날줄 알았는데 오류가 발생했다.
오류의 메세지는 아래와 같다.
- No overload matches this call.
Overload 1 of 3, '(options: DefinedInitialDataInfiniteOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, QueryKey, unknown>, queryClient?: QueryClient | undefined): DefinedUseInfiniteQueryResult<...>', gave the following error.
Argument of type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' is not assignable to parameter of type 'DefinedInitialDataInfiniteOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, QueryKey, unknown>'.
Overload 2 of 3, '(options: UndefinedInitialDataInfiniteOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, QueryKey, unknown>, queryClient?: QueryClient | undefined): UseInfiniteQueryResult<...>', gave the following error.Property 'initialPageParam' is missing in type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' but required in type 'UseInfiniteQueryOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, IProductPublicFindListResponse<...>, QueryKey, unknown>'.
Argument of type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' is not assignable to parameter of type 'UndefinedInitialDataInfiniteOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, QueryKey, unknown>'.
Overload 3 of 3, '(options: UseInfiniteQueryOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, IProductPublicFindListResponse<...>, QueryKey, unknown>, queryClient?: QueryClient | undefined): UseInfiniteQueryResult<...>', gave the following error.Property 'initialPageParam' is missing in type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' but required in type 'UseInfiniteQueryOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, IProductPublicFindListResponse<...>, QueryKey, unknown>'.
Argument of type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' is not assignable to parameter of type 'UseInfiniteQueryOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, IProductPublicFindListResponse<...>, QueryKey, unknown>'.Property 'initialPageParam' is missing in type '{ queryKey: string[]; queryFn: ({ pageParam }: { queryKey: QueryKey; signal: AbortSignal; pageParam: unknown; direction: FetchDirection; meta: Record<string, unknown> | undefined; }) => Promise<...>; getNextPageParam: (lastPage: IProductPublicFindListResponse<...>) => number | undefined; }' but required in type 'UseInfiniteQueryOptions<IProductPublicFindListResponse<IApiResponse[]>, Error, InfiniteData<IProductPublicFindListResponse<IApiResponse[]>, unknown>, IProductPublicFindListResponse<...>, QueryKey, unknown>'.
다 읽어볼 필요는 없고 핵심은
Property 'initialPageParam' is missing in type 이였다.
프로퍼티중 initialPageParam 이 없어서 오류가 발생한거였는데, 내가 이해한 바로는 queryFn에서 pageParam을 1로 줬는데 pageParam을 안줘도 되는거 아닌가? 라고 생각하였는데 이 돌은 차이점이 존재했다.
1. pageParam
우선 queryFn에서 사용하는 pageParam은 queryFn 이 호출될 때의 현재 요쳥할 페이지 번호이다.
그래서 무한스크롤을 구현할 때 사용자가 스크롤을 한다면 1에서 다음 페이지를 요청한 뒤 2로 값이 자동으로 증가하여 다음페이지를 요청하는 것이다.
정리하자면 pageParam=1 은 첫 번째 페이지의 데이터를 요청하는 것이다.
2. initialPageParam
initialPageParam은 useInfiniteQuery 가 처음 실행될 때 사용되는 초기페이지 번호이다. 이 값은 쿼리가 처음 실행될 때만 사용이 되고, 그 이후에는 pageParam이 업데이트되어 사용된다.
그러면 둘 다 첫 번째 페이지를 요청하는것이 아닌가? 라고 생각할 수 있는데 정답은 아니다.
pageParam은 각 요청이 들어올때의 현재 페이지를 관리하는 것이고 initialPageParam은 쿼리가 시작될 때의 첫 번째 페이지를 설정하는 것이다.
initialPageParam은 선택사항으로 알고있었는데 다른 블로그들을 찾아보니 initialPageParam은 필수값이라고 한다.
아직은 공식문서를 보고 바로 이해하지는 못하겠는데 그래도 공식문서를 보며 참고하고 적응해야겠다..
'리액트' 카테고리의 다른 글
React tailwindCSS image (0) | 2024.12.25 |
---|---|
react query refetching (0) | 2024.12.23 |
flatMap() (2) | 2024.12.21 |
Docker 공부 (1) | 2024.12.19 |
tanstackquery [useInfiniteQuery] (0) | 2024.12.19 |