Links & Request Batching
Similar to urql's exchanges or Apollo's links. Links enables you to customize the flow of data between tRPC Client and the tRPC-server.
Request Batching
Request batching is automatically enabled which batches your requests to the server, this can make the below code produce exactly one HTTP request and on the server exactly one database query:
ts
// below will be done in the same request when batching is enabledconst somePosts = await Promise.all([client.query('post.byId', 1),client.query('post.byId', 2),client.query('post.byId', 3),])
ts
// below will be done in the same request when batching is enabledconst somePosts = await Promise.all([client.query('post.byId', 1),client.query('post.byId', 2),client.query('post.byId', 3),])
Customizing data flow
The below examples assuming you use Next.js, but the same as below can be added if you use the vanilla tRPC client
Setting a maximum batch size
This limits the number of requests that can be sent together in batch ( useful to prevent the url from getting too large and run into HTTP error 413 ).
server.tsts
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';// 👇 import the httpBatchLinkimport { httpBatchLink } from '@trpc/client/links/httpBatchLink';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpBatchLink({url: '/api/trpc',maxBatchSize: 10 // a reasonable size}),],};},})(MyApp);
server.tsts
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';// 👇 import the httpBatchLinkimport { httpBatchLink } from '@trpc/client/links/httpBatchLink';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpBatchLink({url: '/api/trpc',maxBatchSize: 10 // a reasonable size}),],};},})(MyApp);
Disabling request batching
1. Disable batching
on your server:
In your [trpc].ts
:
pages/api/trpc/[trpc].tsts
export default trpcNext.createNextApiHandler({// [...]// 👇 disable batchingbatching: {enabled: false,},});
pages/api/trpc/[trpc].tsts
export default trpcNext.createNextApiHandler({// [...]// 👇 disable batchingbatching: {enabled: false,},});
2. Use batch-free link in your tRPC Client
pages/_app.tsxtsx
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';// 👇 import the httpLinkimport { httpLink } from '@trpc/client/links/httpLink';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpLink({url: '/api/trpc',}),],};},// ssr: false,})(MyApp);
pages/_app.tsxtsx
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';// 👇 import the httpLinkimport { httpLink } from '@trpc/client/links/httpLink';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpLink({url: '/api/trpc',}),],};},// ssr: false,})(MyApp);
Using a splitLink
to control request flow
Disable batching for certain requests
1. Configure client / _app.tsx
pages/_app.tsxtsx
import { withTRPC } from '@trpc/next';import { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { httpLink } from '@trpc/client/links/httpLink';import { splitLink } from '@trpc/client/links/splitLink';// [..]export default withTRPC<AppRouter>({config() {const url = `http://localhost:3000`;return {links: [splitLink({condition(op) {// check for context property `skipBatch`return op.context.skipBatch === true;},// when condition is true, use normal requesttrue: httpLink({url,}),// when condition is false, use batchingfalse: httpBatchLink({url,}),}),],};},})(MyApp);
pages/_app.tsxtsx
import { withTRPC } from '@trpc/next';import { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { httpLink } from '@trpc/client/links/httpLink';import { splitLink } from '@trpc/client/links/splitLink';// [..]export default withTRPC<AppRouter>({config() {const url = `http://localhost:3000`;return {links: [splitLink({condition(op) {// check for context property `skipBatch`return op.context.skipBatch === true;},// when condition is true, use normal requesttrue: httpLink({url,}),// when condition is false, use batchingfalse: httpBatchLink({url,}),}),],};},})(MyApp);
2. Perform request without batching
MyComponent.tsxtsx
export function MyComponent() {const postsQuery = trpc.useQuery(['posts'], {context: {skipBatch: true,},});return (<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>)})
MyComponent.tsxtsx
export function MyComponent() {const postsQuery = trpc.useQuery(['posts'], {context: {skipBatch: true,},});return (<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>)})
or:
client.tsts
const postResult = client.query('posts', null, {context: {skipBatch: true,},})
client.tsts
const postResult = client.query('posts', null, {context: {skipBatch: true,},})
Creating a custom link
pages/_app.tsxtsx
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { TRPCLink } from '@trpc/client';const customLink: TRPCLink<AppRouter> = (runtime) => {// here we just got initialized in the app - this happens once per app// useful for storing cache for instancereturn ({ prev, next, op }) => {// this is when passing the result to the next linknext(op, (result) => {// this is when we've gotten result from the serverif (result instanceof Error) {// maybe send to bugsnag?}prev(result);});};};export default withTRPC<AppRouter>({config() {return {links: [customLink,// [..]// ❗ Make sure to end with a `httpBatchLink` or `httpLink`],};},// ssr: false})(MyApp);
pages/_app.tsxtsx
import type { AppRouter } from 'pages/api/trpc/[trpc]';import { TRPCLink } from '@trpc/client';const customLink: TRPCLink<AppRouter> = (runtime) => {// here we just got initialized in the app - this happens once per app// useful for storing cache for instancereturn ({ prev, next, op }) => {// this is when passing the result to the next linknext(op, (result) => {// this is when we've gotten result from the serverif (result instanceof Error) {// maybe send to bugsnag?}prev(result);});};};export default withTRPC<AppRouter>({config() {return {links: [customLink,// [..]// ❗ Make sure to end with a `httpBatchLink` or `httpLink`],};},// ssr: false})(MyApp);