--- id: paginated-queries title: Paginated / Lagged Queries ref: docs/framework/react/guides/paginated-queries.md replace: { 'useQuery': 'injectQuery', 'useInfiniteQuery': 'injectInfiniteQuery', 'hook': 'function', } --- [//]: # 'Example' ```ts const projectsQuery = injectQuery(() => ({ queryKey: ['projects', page()], queryFn: fetchProjects, })) ``` [//]: # 'Example' [//]: # 'Example2' ```angular-ts @Component({ selector: 'pagination-example', template: `

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 suppressed 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 re-fetched invisibly in the background.

@if (projectsQuery.status() === 'pending') {
Loading...
} @else if (projectsQuery.status() === 'error') {
Error: {{ projectsQuery.error().message }}
} @else {
@for (project of projectsQuery.data().projects; track project.id) {

{{ project.name }}

}
}
Current Page: {{ page() + 1 }}
@if (projectsQuery.isFetching()) { Loading... }
`, }) export class PaginationExampleComponent { page = signal(0) readonly #queryClient = inject(QueryClient) readonly projectsQuery = injectQuery(() => ({ queryKey: ['projects', this.page()], queryFn: () => lastValueFrom(fetchProjects(this.page())), placeholderData: keepPreviousData, staleTime: 5000, })) constructor() { effect(() => { // Prefetch the next page! if ( !this.projectsQuery.isPlaceholderData() && this.projectsQuery.data()?.hasMore ) { void this.#queryClient .query({ queryKey: ['projects', this.page() + 1], queryFn: () => lastValueFrom(fetchProjects(this.page() + 1)), }) .catch(noop) } }) } previousPage() { this.page.update((old) => Math.max(old - 1, 0)) } nextPage() { this.page.update((old) => this.projectsQuery.data()?.hasMore ? old + 1 : old, ) } } ``` [//]: # 'Example2'