靜態網站產生
靜態網站產生需要在每個頁面的 getStaticProps
中執行 tRPC 查詢。
可以使用 伺服器端輔助程式 來預先擷取查詢、將其脫水,並傳遞至頁面。然後,查詢會自動擷取 trpcState
並將其用作初始值。
在 getStaticProps
中擷取資料
pages/posts/[id].tsxtsx
import { createServerSideHelpers } from '@trpc/react-query/server';import {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import { prisma } from 'server/context';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';export async function getStaticProps(context: GetStaticPropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson, // optional - adds superjson serialization});const id = context.params?.id as string;// prefetch `post.byId`await helpers.post.byId.prefetch({ id });return {props: {trpcState: helpers.dehydrate(),id,},revalidate: 1,};}export const getStaticPaths: GetStaticPaths = async () => {const posts = await prisma.post.findMany({select: {id: true,},});return {paths: posts.map((post) => ({params: {id: post.id,},})),// https://nextjs.dev.org.tw/docs/pages/api-reference/functions/get-static-paths#fallback-blockingfallback: 'blocking',};};export default function PostViewPage(props: InferGetStaticPropsType<typeof getStaticProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since we're using `fallback: "blocking"`return <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString('en-us')}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}
pages/posts/[id].tsxtsx
import { createServerSideHelpers } from '@trpc/react-query/server';import {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import { prisma } from 'server/context';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';export async function getStaticProps(context: GetStaticPropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson, // optional - adds superjson serialization});const id = context.params?.id as string;// prefetch `post.byId`await helpers.post.byId.prefetch({ id });return {props: {trpcState: helpers.dehydrate(),id,},revalidate: 1,};}export const getStaticPaths: GetStaticPaths = async () => {const posts = await prisma.post.findMany({select: {id: true,},});return {paths: posts.map((post) => ({params: {id: post.id,},})),// https://nextjs.dev.org.tw/docs/pages/api-reference/functions/get-static-paths#fallback-blockingfallback: 'blocking',};};export default function PostViewPage(props: InferGetStaticPropsType<typeof getStaticProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since we're using `fallback: "blocking"`return <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString('en-us')}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}
請注意,react-query
的預設行為是在掛載時於用戶端重新擷取資料,因此如果你僅想透過 getStaticProps
擷取資料,則需要在查詢選項中將 refetchOnMount
和 refetchOnWindowFocus
設為 false
。
如果你想將 API 要求次數降至最低,這可能是較好的做法,例如,如果你正在使用受限速率的第三方 API。
這可以針對每個查詢執行
tsx
const data = trpc.example.useQuery(// if your query takes no input, make sure that you don't// accidentally pass the query options as the first argumentundefined,{ refetchOnMount: false, refetchOnWindowFocus: false },);
tsx
const data = trpc.example.useQuery(// if your query takes no input, make sure that you don't// accidentally pass the query options as the first argumentundefined,{ refetchOnMount: false, refetchOnWindowFocus: false },);
或針對全域執行,如果應用程式中的每個查詢都應以相同方式運作
utils/trpc.tstsx
import { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(opts) {return {links: [httpBatchLink({url: `${getBaseUrl()}/api/trpc`,}),],// Change options globallyqueryClientConfig: {defaultOptions: {queries: {refetchOnMount: false,refetchOnWindowFocus: false,},},},},},});
utils/trpc.tstsx
import { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(opts) {return {links: [httpBatchLink({url: `${getBaseUrl()}/api/trpc`,}),],// Change options globallyqueryClientConfig: {defaultOptions: {queries: {refetchOnMount: false,refetchOnWindowFocus: false,},},},},},});
如果你的應用程式包含靜態和動態查詢的混合,請小心使用此方法。