Skip to main content
Version: 11.x

Suspense

信息
  • 确保你使用的是最新版本的 React

    ¥Ensure you're on the latest version of React

  • 如果你对 Next.js 中 tRPC 的自动 SSR 使用暂挂,则如果查询失败,即使你有 <ErrorBoundary />,整页也会在服务器上崩溃

    ¥If you use suspense with tRPC's automatic SSR in Next.js, the full page will crash on the server if a query fails, even if you have an <ErrorBoundary />

用法

¥Usage

提示

useSuspenseQueryuseSuspenseInfiniteQuery 都返回 [data, query] 元组,以便轻松直接使用数据并将变量重命名为描述性内容

¥useSuspenseQuery & useSuspenseInfiniteQuery both return a [data, query]-tuple, to make it easy to directly use your data and renaming the variable to something descriptive

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() 的 Suspense 等效项。

¥Suspense equivalent of 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 <>{/* [...] */}</>;
};

预取

¥Prefetching

通过在 Suspense 组件渲染之前预取查询数据(有时称为 "render-as-you-fetch")可以提高 Suspense 查询的性能。

¥The performance of suspense queries can be improved by prefetching the query data before the Suspense component is rendered (this is sometimes called "render-as-you-fetch").

注意
  • 预取和即取即渲染模型非常依赖于你使用的框架和路由。我们建议你阅读框架路由文档以及 @tanstack/react-query docs,以了解如何实现这些模式。

    ¥Prefetching and the render-as-you-fetch model are very dependent on the framework and router you are using. We recommend reading your frameworks router docs along with the @tanstack/react-query docs to understand how to implement these patterns.

  • 如果你正在使用 Next.js,请查看 服务器端助手 上的文档以实现服务器端预取。

    ¥If you are using Next.js please look at the docs on Server-Side Helpers to implement server-side prefetching.

路由级预取

¥Route-level prefetching

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 进行组件级预取

¥Component-level prefetching with 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 进行组件级预取

¥Component-level prefetching with 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>
);
}