useInfiniteQuery
info
- Your procedure needs to accept a
cursor
input ofany
type - For more details on infinite queries read the react-query docs
- In this example we're using Prisma - see their docs on cursor-based pagination
Example Procedure
server/routers/_app.ts
import { initTRPC } from '@trpc/server'
import { Context } from './[trpc]';
export const t = initTRPC()()
export const appRouter = t.router({
infinitePosts: t
.procedure
.input(z.object({
limit: z.number().min(1).max(100).nullish(),
cursor: z.number().nullish(), // <-- "cursor" needs to exist, but can be any type
})),
.query(({ input }) => {
const limit = input.limit ?? 50;
const { cursor } = input;
const items = await prisma.post.findMany({
take: limit + 1, // get an extra item at the end which we'll use as next cursor
where: {
title: {
contains: 'Prisma' /* Optional filter */,
},
},
cursor: cursor ? { myCursor: cursor } : undefined,
orderBy: {
myCursor: 'asc',
},
})
let nextCursor: typeof cursor | null = null;
if (items.length > limit) {
const nextItem = items.pop()
nextCursor = nextItem!.myCursor;
}
return {
items,
nextCursor,
};
})
})
Example React Component
components/MyComponent.tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const myQuery = trpc.proxy.infinitePosts.useInfiniteQuery(
{
limit: 10,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
},
);
// [...]
}
Helpers
getInfiniteQueryData()
This helper gets the currently cached data from an existing infinite query
components/MyComponent.tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.proxy.infinitePosts.add.useMutation({
onMutate({ post }) {
await utils.cancelQuery(['infinitePosts']);
const allPosts = utils.getInfiniteQueryData(['infinitePosts', { limit: 10 }]);
// [...]
}
})
}
setInfiniteQueryData()
This helper allows you to update a queries cached data
components/MyComponent.tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.proxy.infinitePosts.delete.useMutation({
onMutate({ post }) {
await utils.cancelQuery(['infinitePosts']);
utils.setInfiniteQueryData(['infinitePosts', { limit: 10 }], (data) => {
if (!data) {
return {
pages: [],
pageParams: []
}
}
return {
...data,
pages: data.pages.map((page) => {
...page,
items: page.items.filter((item) => item.status === 'published')
})
}
});
}
});
// [...]
}