Use useInfiniteQuery
instead of useQuery
, if you want to show large
data gradually more. For instance, you have many numbered pages, and you
want to show the first ten pages initially. After clicking on
Show more pages
, the user should see three pages more than before. For
this case, you can useInfiniteQuery
as shown in the following example.
import { useInfiniteQuery } from "blitz"
import getProjects from "app/projects/queries/getProjects"
function Projects(props) {
const [
projectPages,
{ isFetching, isFetchingNextPage, fetchNextPage, hasNextPage },
] = useInfiniteQuery(
getProjects,
(page = { take: 3, skip: 0 }) => page,
{
getNextPageParam: (lastPage) => lastPage.nextPage,
}
)
return (
<>
{projectPages.map((page, i) => (
<React.Fragment key={i}>
{page.projects.map((project) => (
<p key={project.id}>{project.name}</p>
))}
</React.Fragment>
))}
<div>
<button
onClick={() => fetchNextPage()}
disabled={!hasNextPage || !!isFetchingNextPage}
>
{isFetchingNextPage
? "Loading more..."
: hasNextPage
? "Load More"
: "Nothing more to load"}
</button>
</div>
<div>
{isFetching && !isFetchingNextPage ? "Fetching..." : null}
</div>
</>
)
}
And here's the query to work with that:
import { paginate, resolver } from "blitz"
import db, { Prisma } from "db"
interface GetProjectsInput
extends Pick<
Prisma.ProjectFindManyArgs,
"where" | "orderBy" | "skip" | "take"
> {}
export default resolver.pipe(
resolver.authorize(),
async ({ where, orderBy, skip = 0, take = 100 }: GetProjectsInput) => {
const {
items: projects,
hasMore,
nextPage,
count,
} = await paginate({
skip,
take,
count: () => db.project.count({ where }),
query: (paginateArgs) =>
db.project.findMany({ ...paginateArgs, where, orderBy }),
})
return {
projects,
nextPage,
hasMore,
count,
}
}
)
const [
pagesOfQueryResults,
{
pageParams,
fetchNextPage,
fetchPreviousPage,
hasNextPage,
hasPreviousPage,
isFetchingNextPage,
isFetchingPreviousPage,
...extras
},
] = useInfiniteQuery(queryResolver, getQueryInputArguments, {
...options,
getNextPageParam: (lastPage, allPages) => lastPage.nextPage,
getPreviousPageParam: (firstPage, allPages) => firstPage.nextPage,
})
queryResolver:
A Blitz query resolvergetQueryInputArguments: (fetchNextPageVariable) => queryInputArguments
queryInputArguments
fetchNextPageVariable
is undefined
.fetchNextPageVariable
is whatever is returned
from getNextPageParam()
options
The options are identical to the options for the useQuery hook with the addition of the following:
getNextPageParam: (lastPage, allPages) => unknown | undefined
getQueryInputArguments()
.undefined
to indicate there is no next page available.getPreviousPageParam: (firstPage, allPages) => unknown | undefined
getQueryInputArguments()
.undefined
to indicate there is no previous page available.[pagesOfQueryResults, queryExtras]
pagesOfQueryResults: TData[]
queryExtras: Object
The query extras for useInfiniteQuery
are identical to the query extas
for the useQuery hook with the addition of the
following:
pageParams: unknown[]
isFetchingNextPage: boolean
true
while fetching the next page with fetchNextPage
.isFetchingPreviousPage: boolean
true
while fetching the previous page with
fetchPreviousPage
.fetchNextPage: (options?: FetchNextPageOptions) => Promise<UseInfiniteQueryResult>
options.pageParam: unknown
allows you to manually specify a page
param instead of using getNextPageParam
.fetchPreviousPage: (options?: FetchPreviousPageOptions) => Promise<UseInfiniteQueryResult>
options.pageParam: unknown
allows you to manually specify a page
param instead of using getPreviousPageParam
.hasNextPage: boolean
true
if there is a next page to be fetched (known via
the getNextPageParam
option).hasPreviousPage: boolean
true
if there is a previous page to be fetched (known
via the getPreviousPageParam
option).setQueryData()
- Function(newData, opts) => void
newData
can be an object of new data or a function that receives the
old data and returns the new datarefetch()
to
ensure the data is correct. Disable refetch by passing an options
object {refetch: false}
as the second argument.setQueryData()