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

서스펜스

비공식 베타 번역

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

정보
  • React 최신 버전을 사용 중인지 확인하세요
  • Next.js에서 tRPC의 자동 SSR과 함께 서스펜스를 사용할 경우, 쿼리 실패 시 <ErrorBoundary />가 있어도 서버 측에서 전체 페이지가 중단됩니다

사용법

useSuspenseQueryuseSuspenseInfiniteQuery는 모두 [data, query]-튜플을 반환하여 데이터에 직접 접근하고 변수명을 설명적인 이름으로 변경하기 쉽게 합니다

useSuspenseQuery()

tsx
// @filename: pages/index.tsx
import React from 'react';
import { trpc } from '../utils/trpc';
 
function PostView() {
const [post, postQuery] = trpc.post.byId.useSuspenseQuery({ id: '1' });
const post: { id: string; title: string; }
 
return <>{/* ... */}</>;
}
tsx
// @filename: pages/index.tsx
import React from 'react';
import { trpc } from '../utils/trpc';
 
function PostView() {
const [post, postQuery] = trpc.post.byId.useSuspenseQuery({ id: '1' });
const post: { id: string; title: string; }
 
return <>{/* ... */}</>;
}

useSuspenseInfiniteQuery()

tsx
// @filename: pages/index.tsx
import React from 'react';
import { trpc } from '../utils/trpc';
function PostView() {
const [{ pages }, allPostsQuery] = trpc.post.all.useSuspenseInfiniteQuery(
{},
{
getNextPageParam(lastPage) {
return lastPage.nextCursor;
},
},
);
const { isFetching, isFetchingNextPage, fetchNextPage, hasNextPage } =
allPostsQuery;
return <>{/* ... */}</>;
}
tsx
// @filename: pages/index.tsx
import React from 'react';
import { trpc } from '../utils/trpc';
function PostView() {
const [{ pages }, allPostsQuery] = trpc.post.all.useSuspenseInfiniteQuery(
{},
{
getNextPageParam(lastPage) {
return lastPage.nextCursor;
},
},
);
const { isFetching, isFetchingNextPage, fetchNextPage, hasNextPage } =
allPostsQuery;
return <>{/* ... */}</>;
}

useSuspenseQueries()

useQueries()의 서스펜스 버전입니다.

tsx
const Component = (props: { postIds: string[] }) => {
const [posts, postQueries] = trpc.useSuspenseQueries((t) =>
props.postIds.map((id) => t.post.byId({ id })),
);
return <>{/* [...] */}</>;
};
tsx
const Component = (props: { postIds: string[] }) => {
const [posts, postQueries] = trpc.useSuspenseQueries((t) =>
props.postIds.map((id) => t.post.byId({ id })),
);
return <>{/* [...] */}</>;
};

프리페칭

서스펜스 컴포넌트 렌더링 전에 쿼리 데이터를 프리페칭하면 서스펜스 쿼리 성능을 개선할 수 있습니다 (이를 "render-as-you-fetch"라고도 함).

참고
  • 프리페칭과 render-as-you-fetch 모델은 사용 중인 프레임워크 및 라우터에 크게 의존합니다. 해당 패턴 구현 방법을 이해하려면 @tanstack/react-query 문서와 함께 사용 중인 프레임워크의 라우터 문서를 참고하세요
  • Next.js 사용 시 서버 측 프리페칭 구현을 위해 Server-Side Helpers 문서를 확인하세요

라우트 수준 프리페칭

tsx
const utils = createTRPCQueryUtils({ queryClient, client: trpcClient });
// tanstack router/ react router loader
const loader = async (params: { id: string }) =>
utils.post.byId.ensureQueryData({ id: params.id });
tsx
const utils = createTRPCQueryUtils({ queryClient, client: trpcClient });
// tanstack router/ react router loader
const loader = async (params: { id: string }) =>
utils.post.byId.ensureQueryData({ id: params.id });

컴포넌트 수준 프리페칭 (usePrefetchQuery 사용)

tsx
import { trpc } from '../utils/trpc';
function PostViewPage(props: { postId: string }) {
trpc.post.byId.usePrefetchQuery({ id: props.postId });
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}
tsx
import { trpc } from '../utils/trpc';
function PostViewPage(props: { postId: string }) {
trpc.post.byId.usePrefetchQuery({ id: props.postId });
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}

컴포넌트 수준 프리페칭 (usePrefetchInfiniteQuery 사용)

tsx
import { trpc } from '../utils/trpc';
// will have to be passed to the child PostView `useSuspenseInfiniteQuery`
export const getNextPageParam = (lastPage) => lastPage.nextCursor;
function PostViewPage(props: { postId: string }) {
trpc.post.all.usePrefetchInfiniteQuery({}, { getNextPageParam });
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}
tsx
import { trpc } from '../utils/trpc';
// will have to be passed to the child PostView `useSuspenseInfiniteQuery`
export const getNextPageParam = (lastPage) => lastPage.nextCursor;
function PostViewPage(props: { postId: string }) {
trpc.post.all.usePrefetchInfiniteQuery({}, { getNextPageParam });
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}