Blitz is now in beta! 🎉 1.0 expected this April
Back to Documentation Menu

useInfiniteQuery

Topics

Jump to a Topic

Example

import {useInfiniteQuery} from "blitz"
import getProjectsInfinite from "app/projects/queries/getProjectsInfinite"

function Projects(props) {
  const [
    groupedProjects,
    {isFetching, isFetchingMore, fetchMore, canFetchMore},
  ] = useInfiniteQuery(
    getProjectsInfinite,
    (page = {take: 3, skip: 0}) => page,
    {
      getFetchMore: (lastGroup) => lastGroup.nextPage,
    },
  )
  return (
    <>
      {groupedProjects.map((group, i) => (
        <React.Fragment key={i}>
          {group.projects.map((project) => (
            <p key={project.id}>{project.name}</p>
          ))}
        </React.Fragment>
      ))}
      <div>
        <button
          onClick={() => fetchMore()}
          disabled={!canFetchMore || !!isFetchingMore}
        >
          {isFetchingMore
            ? "Loading more..."
            : canFetchMore
            ? "Load More"
            : "Nothing more to load"}
        </button>
      </div>
      <div>{isFetching && !isFetchingMore ? "Fetching..." : null}</div>
    </>
  )
}

And here's the query to work with that:

export default async function getProjectsInfinite({
  where,
  orderBy,
  take,
  skip,
}: GetProjectsInfiniteInput) {
  const projects = await db.project.findMany({
    where,
    orderBy,
    take,
    skip,
  })

  const count = await db.project.count()
  const hasMore = skip! + take! < count
  const nextPage = hasMore ? {take, skip: skip! + take!} : null

  return {
    projects,
    nextPage,
  }
}

API

const [
  groupedQueryFunctionResults,
  {
    isFetching,
    failureCount,
    refetch,
    fetchMore,
    canFetchMore,
    setQueryData,
  }
] = useQuery(queryResolver, getQueryInputArguments, {
  getFetchMore: (lastPage, allPages) => fetchMoreVariable
  ...queryOptions,
})

Arguments

  • queryResolver: A Blitz query resolver
    • Required
  • getQueryInputArguments: (fetchMoreVariable) => queryInputArguments
    • Required
    • A function that accepts the current page options and returns the queryInputArguments
    • On the first page load, fetchMoreVariable is undefined.
    • For subsequent pages, fetchMoreVariable is whatever is returned from getFetchMore()
  • options
    • Optional

Options

The options are identical to the options for the useQuery hook with the addition of the following:

  • getFetchMore: Function(lastPage, allPages) => fetchMoreVariable | Boolean
    • When new data is received for this query, this function receives both the last page of the infinite list of data and the full array of all pages.
    • It should return a single variable that will be passed as the argument to getQueryInputArguments()

Returns

[groupedQueryFunctionResults, queryExtras]

groupedQueryFunctionResults: Array<any>
  • Defaults to [].
  • The array will contain each "page" of data that has been requested
queryExtras: Object
  • isFetching: Boolean
    • Will be true if the query is currently fetching, including background fetching.
  • failureCount: Integer
    • The failure count for the query.
    • Incremented every time the query fails.
    • Reset to 0 when the query succeeds.
  • refetch() - Function({ force, throwOnError }) => void
    • A function to manually refetch the query if it is stale.
    • To bypass the stale check, you can pass the force: true option and refetch it regardless of it's freshness
    • If the query errors, the error will only be logged. If you want an error to be thrown, pass the throwOnError: true option
  • fetchMore() - Function(fetchMoreVariableOverride, { previous }) => Promise
    • This function allows you to fetch the next "page" of results.
    • fetchMoreVariableOverride allows you to optionally override the fetch more variable returned from your getCanFetchMore option to your query function to retrieve the next page of results.
    • previous option which will determine if the data you are fetching is should be prepended instead of appended to your infinite list. e.g. fetchMore(nextPageVars, { previous: true })
  • canFetchMore: Boolean
    • If using paginated mode, this will be true if there is more data to be fetched (known via the required getFetchMore option function).
  • setQueryData() - Function(newData, opts) => void
    • A function to manually update the cache for a query.
    • newData can be an object of new data or a function that receives the old data and returns the new data
    • This is often used to instantly update the cache after submitting a form
    • After updating the cache, this will automatically call refetch() to ensure the data is correct. Disable refetch by passing an options object {refetch: false} as the second argument.
    • See the Blitz mutation usage docs for example usage of setQueryData()

Idea for improving this page? Edit it on Github.