Description
Describe the bug
Selectors in combination with useQuery
look very good. Creating multiple hooks on top of the original useQuery
hook, allowing you to get different parts of the data out the query result as described in https://tkdodo.eu/blog/react-query-data-transformations in particular (e.g. useTodosCount
, useTodos
, useTodo(id)
).
Now, when using useInfiniteQuery
, I'm able to do the same thing. But TypeScript won't let me. It forces me into the InfiniteData
type, hence the { pages, pageParams }
format.
To Reproduce
What I'd like to do is twofold:
- Get an array of all items concatenated over all pages
- Get the total count of items available in the backend
Type definitions of a simplified example:
interface Entity {
id: string;
// ...
}
interface APIResponse {
total: number; // Total number of entities available in the backend
totalPages: number; // Total number of pages with entities
items: Entity[]; // The entities for this requested page
}
interface DesiredDataResult {
total: number; // Same value as total in APIResponse
items: Entity[]; // Concatenation of all items on all fetched pages (flatMap of `page.items`)
}
Now, I try to build the DesiredDataResult
in the selector:
const { data: result } = useInfiniteQuery(
['entities', 'list'],
async ({ pageParam = 0 }) => getPageFromAPI(pageParam),
{
getNextPageParam: (lastPage, allPages) =>
lastPage.totalPages > allPages.length ? allPages.length : undefined,
select: React.useCallback(
(data: InfiniteData<APIResponse>) => ({
total: data.pages[0].total,
entities: data.pages.flatMap((page) => page.items),
}),
[],
),
},
);
And I get this TypeScript error. It wants me to use the { pages, pageParams }
type.
Type '(data: InfiniteData<APIResponse>) => { total: number; entities: Entity[]; }' is not assignable to type '(data: InfiniteData<APIResponse>) => InfiniteData<APIResponse>'.
Type '{ total: number; entities: Entity[]; }' is missing the following properties from type 'InfiniteData<APIResponse>': pages, pageParams ts(2322)
Therefore, selectors in combination with useInfiniteQuery
are less expressive than with useQuery
. Maybe I'm missing something?
Expected behavior
I would have expected to be able to apply selectors with the same expressiveness as useQuery
on useInfiniteQuery
.
Desktop (please complete the following information):
- OS: macOS
- Browser: Safari
- Version: 14.1.2