メインコンテンツへスキップ
バージョン: 11.x

サスペンス

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

情報
  • Reactの最新バージョンを使用していることを確認してください
  • Next.jsでのtRPCの自動SSRとサスペンスを併用する場合、クエリが失敗すると<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を使用している場合は、サーバーサイドプリフェッチを実装するためにServer-Side Helpersのドキュメントを参照してください

ルートレベルのプリフェッチ

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>
);
}