본문으로 건너뛰기
버전: 11.x

Suspense

정보
  • 최신 버전의 React를 사용 중인지 확인합니다
  • tRPC의 자동 Next.js SSR을 suspense와 함께 사용하는 경우, 쿼리가 실패하면 <ErrorBoundary />가 있더라도 서버에서 전체 페이지가 충돌합니다

사용법

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

useSuspenseQuery()

tsx
import { trpc } from '../utils/trpc';
 
function PostView() {
const [post, postQuery] = trpc.post.byId.useSuspenseQuery({ id: '1' });
 
return <>{/* ... */}</>;
}
tsx
import { trpc } from '../utils/trpc';
 
function PostView() {
const [post, postQuery] = trpc.post.byId.useSuspenseQuery({ id: '1' });
 
return <>{/* ... */}</>;
}

useSuspenseInfiniteQuery()

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

useSuspenseQueries()

useQueries()의 Suspense 버전입니다.

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

사전 가져오기

Suspense 컴포넌트가 렌더링되기 전에 쿼리 데이터를 사전 가져오면 suspense 쿼리의 성능을 향상시킬 수 있습니다(이를 "render-as-you-fetch"라고도 합니다).

노트
  • 사전 가져오기와 render-as-you-fetch 모델은 사용하는 프레임워크와 라우터에 크게 의존합니다. 이러한 패턴을 구현하는 방법을 이해하려면 프레임워크의 라우터 문서와 함께 @tanstack/react-query 문서를 읽는 것을 권장합니다.
  • Next.js를 사용하는 경우 서버 측 사전 가져오기를 구현하려면 서버 측 헬퍼 문서를 참고하세요.

라우트 수준 사전 가져오기

tsx
import { createTRPCQueryUtils } from '@trpc/react-query';
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { QueryClient } from '@tanstack/react-query';
import type { AppRouter } from './server';
 
const queryClient = new QueryClient();
const trpcClient = createTRPCClient<AppRouter>({ links: [httpBatchLink({ url: 'http://localhost:3000' })] });
const utils = createTRPCQueryUtils({ queryClient, client: trpcClient });
 
// tanstack router/ react router loader
const loader = async (params: { id: string }) =>
utils.post.byId.ensureData({ id: params.id });
tsx
import { createTRPCQueryUtils } from '@trpc/react-query';
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { QueryClient } from '@tanstack/react-query';
import type { AppRouter } from './server';
 
const queryClient = new QueryClient();
const trpcClient = createTRPCClient<AppRouter>({ links: [httpBatchLink({ url: 'http://localhost:3000' })] });
const utils = createTRPCQueryUtils({ queryClient, client: trpcClient });
 
// tanstack router/ react router loader
const loader = async (params: { id: string }) =>
utils.post.byId.ensureData({ id: params.id });

usePrefetchQuery를 사용한 컴포넌트 수준 사전 가져오기

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

usePrefetchInfiniteQuery를 사용한 컴포넌트 수준 사전 가져오기

tsx
import React, { Suspense } from 'react';
import { trpc } from '../utils/trpc';
import type { PostPage } from '../server';
 
function PostView(props: { postId: string }) {
return <></>;
}
 
function PostViewPage(props: { postId: string }) {
trpc.post.all.usePrefetchInfiniteQuery(
{},
{
getNextPageParam(lastPage: PostPage) {
return lastPage.nextCursor;
},
initialCursor: '',
},
);
 
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}
tsx
import React, { Suspense } from 'react';
import { trpc } from '../utils/trpc';
import type { PostPage } from '../server';
 
function PostView(props: { postId: string }) {
return <></>;
}
 
function PostViewPage(props: { postId: string }) {
trpc.post.all.usePrefetchInfiniteQuery(
{},
{
getNextPageParam(lastPage: PostPage) {
return lastPage.nextCursor;
},
initialCursor: '',
},
);
 
return (
<Suspense>
<PostView postId={props.postId} />
</Suspense>
);
}