Skip to content

React Example: Pagination

Source URL: https://tanstack.com/query/latest/docs/framework/react/examples/pagination

TanStack

Query v5v5

AlphaTry TanStack CLI

Search…

K

Auto

Log In

StartRC

StartRC

Router

Router

Query

Query

Table

Table

DBbeta

DBbeta

AIalpha

AIalpha

Formnew

Formnew

Virtual

Virtual

Pacerbeta

Pacerbeta

Hotkeysalpha

Hotkeysalpha

Storealpha

Storealpha

Devtoolsalpha

Devtoolsalpha

CLIalpha

CLIalpha

More Libraries

More Libraries

BuilderAlpha

BuilderAlpha

FeedBeta

FeedBeta

Maintainers

Maintainers

Partners

Partners

Showcase

Showcase

Blog

Blog

LearnNEW

LearnNEW

Support

Support

Stats

Stats

Discord

Discord

Merch

Merch

GitHub

GitHub

Ethos

Ethos

Tenets

Tenets

Brand Guide

Brand Guide

Docs

Partners

CodeRabbitCodeRabbitCloudflareCloudflareAG GridAG GridSerpAPISerpAPINetlifyNetlifyNeonNeonWorkOSWorkOSClerkClerkConvexConvexElectricElectricPowerSyncPowerSyncSentrySentryRailwayRailwayPrismaPrismaStrapiStrapiUnkeyUnkeyCodeRabbitCodeRabbitCloudflareCloudflareAG GridAG GridSerpAPISerpAPINetlifyNetlifyNeonNeonWorkOSWorkOSClerkClerkConvexConvexElectricElectricPowerSyncPowerSyncSentrySentryRailwayRailwayPrismaPrismaStrapiStrapiUnkeyUnkey

ReactReact

Latest

Search…

K

latest

ReactReact

Latest

Github StackBlitz CodeSandbox

Code ExplorerCode

Interactive SandboxSandbox

  • src

    • pages

      • api

      • index.tsx file iconindex.tsx

  • .gitignore file icon.gitignore

  • README.md file iconREADME.md

  • next.config.js file iconnext.config.js

  • package.json file iconpackage.json

  • tsconfig.json file icontsconfig.json

tsx

import React from 'react'
import {
QueryClient,
QueryClientProvider,
keepPreviousData,
useQuery,
useQueryClient,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
const queryClient = new QueryClient()
export default function App() {
return (
)
}
const fetchProjects = async (
page = 0,
): Promise<{
projects: Array<{ name: string; id: number }>
hasMore: boolean
}> => {
const response = await fetch(`/api/projects?page=${page}`)
return await response.json()
}
function Example() {
const queryClient = useQueryClient()
const [page, setPage] = React.useState(0)
const { status, data, error, isFetching, isPlaceholderData } = useQuery({
queryKey: ['projects', page],
queryFn: () => fetchProjects(page),
placeholderData: keepPreviousData,
staleTime: 5000,
})
// Prefetch the next page!
React.useEffect(() => {
if (!isPlaceholderData && data?.hasMore) {
queryClient.prefetchQuery({
queryKey: ['projects', page + 1],
queryFn: () => fetchProjects(page + 1),
})
}
}, [data, isPlaceholderData, page, queryClient])
return (
<p>
In this example, each page of data remains visible as the next page is
fetched. The buttons and capability to proceed to the next page are also
supressed until the next page cursor is known. Each page is cached as a
normal query too, so when going to previous pages, you'll see them
instantaneously while they are also refetched invisibly in the
background.
</p>
{status === 'pending' ? (
<div>Loading...</div>
) : status === 'error' ? (
<div>Error: {error.message}</div>
) : (
// `data` will either resolve to the latest page's data
// or if fetching a new page, the last successful page's data
{data.projects.map((project) => (
<p key={project.id}>{project.name}</p>
))}
)}
<div>Current Page: {page + 1}</div>
<button
onClick={() => setPage((old) => Math.max(old - 1, 0))}
disabled={page === 0}
>
Previous Page
</button>{' '}
<button
onClick={() => {
setPage((old) => (data?.hasMore ? old + 1 : old))
}}
disabled={isPlaceholderData || !data?.hasMore}
>
Next Page
</button>
{
// Since the last page's data potentially sticks around between page requests,
// we can use `isFetching` to show a background loading
// indicator since our `status === 'pending'` state won't be triggered
isFetching ? <span> Loading...</span> : null
}{' '}
)
}

CodeRabbitCodeRabbitCloudflareCloudflareAG GridAG GridSerpAPISerpAPINetlifyNetlifyNeonNeonWorkOSWorkOSClerkClerkConvexConvexElectricElectricPowerSyncPowerSyncSentrySentryRailwayRailwayPrismaPrismaStrapiStrapiUnkeyUnkey

“If you’re serious about really understanding React Query, there’s no better way than with query.gg”—Tanner Linsley

Learn More](https://query.gg?s=tanstack)