본문 바로가기
버전: 9.x

useInfiniteQuery

비공식 베타 번역

이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →

정보
  • 프로시저는 any 타입의 cursor 입력을 받아야 합니다
  • 무한 쿼리에 대한 자세한 내용은 react-query 문서를 참조하세요
  • 이 예제에서는 Prisma를 사용하고 있습니다 - 커서 기반 페이지네이션에 관한 문서를 확인하세요

예제 프로시저

server/routers/_app.ts
tsx
import * as trpc from '@trpc/server';
import { Context } from './[trpc]';
import { z } from 'zod';
export const appRouter = trpc.router<Context>()
.query('infinitePosts', {
input: z.object({
limit: z.number().min(1).max(100).nullish(),
cursor: z.number().nullish(), // <-- "cursor" needs to exist, but can be any type
}),
async resolve({ 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 | undefined = undefined;
if (items.length > limit) {
const nextItem = items.pop()
nextCursor = nextItem!.myCursor;
}
return {
items,
nextCursor,
};
})
server/routers/_app.ts
tsx
import * as trpc from '@trpc/server';
import { Context } from './[trpc]';
import { z } from 'zod';
export const appRouter = trpc.router<Context>()
.query('infinitePosts', {
input: z.object({
limit: z.number().min(1).max(100).nullish(),
cursor: z.number().nullish(), // <-- "cursor" needs to exist, but can be any type
}),
async resolve({ 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 | undefined = undefined;
if (items.length > limit) {
const nextItem = items.pop()
nextCursor = nextItem!.myCursor;
}
return {
items,
nextCursor,
};
})

예제 React 컴포넌트

components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const myQuery = trpc.useInfiniteQuery(
[
'infinitePosts',
{
limit: 10,
},
],
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
},
);
// [...]
}
components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const myQuery = trpc.useInfiniteQuery(
[
'infinitePosts',
{
limit: 10,
},
],
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
},
);
// [...]
}

헬퍼

getInfiniteQueryData()

이 헬퍼는 기존 무한 쿼리에서 현재 캐시된 데이터를 가져옵니다.

components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.useMutation('infinitePosts.add', {
onMutate({ post }) {
await utils.cancelQuery(['infinitePosts']);
const allPosts = utils.getInfiniteQueryData(['infinitePosts', { limit: 10 }]);
// [...]
}
})
}
components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.useMutation('infinitePosts.add', {
onMutate({ post }) {
await utils.cancelQuery(['infinitePosts']);
const allPosts = utils.getInfiniteQueryData(['infinitePosts', { limit: 10 }]);
// [...]
}
})
}

setInfiniteQueryData()

이 헬퍼를 사용하면 쿼리의 캐시된 데이터를 업데이트할 수 있습니다

components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.useMutation('infinitePosts.delete', {
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')
})
}
});
}
});
// [...]
}
components/MyComponent.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
const utils = trpc.useContext();
const myMutation = trpc.useMutation('infinitePosts.delete', {
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')
})
}
});
}
});
// [...]
}