Saltar al contenido principal
Versión: 11.x

Helpers para el lado del servidor

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Los helpers para el lado del servidor te proporcionan un conjunto de funciones auxiliares que puedes usar para precargar consultas en el servidor. Esto es útil para SSG, pero también para SSR si optas por no usar ssr: true.

La precarga mediante estos helpers permite poblar la caché de consultas en el servidor, lo que significa que estas consultas no tendrán que ejecutarse inicialmente en el cliente.

Hay 2 formas de usar los helpers para el lado del servidor

1. Router interno

Este método se usa cuando tienes acceso directo a tu router de tRPC, por ejemplo, al desarrollar una aplicación monolítica de Next.js.

Usar estos helpers hace que tRPC llame a tus procedimientos directamente en el servidor sin una solicitud HTTP, similar a las llamadas en el lado del servidor. Esto también significa que no tendrás a mano la solicitud y la respuesta como sueles hacer. Asegúrate de instanciar los helpers con un contexto sin req y res, que normalmente se completan mediante la creación del contexto. Recomendamos el concepto de contexto "interno" y "externo" en ese escenario.

ts
import { createServerSideHelpers } from '@trpc/react-query/server';
import { createContext } from './server/context';
import { appRouter } from './server/routers/_app';
import superjson from 'superjson';
 
const helpers = createServerSideHelpers({
router: appRouter,
ctx: await createContext(),
transformer: superjson,
});
ts
import { createServerSideHelpers } from '@trpc/react-query/server';
import { createContext } from './server/context';
import { appRouter } from './server/routers/_app';
import superjson from 'superjson';
 
const helpers = createServerSideHelpers({
router: appRouter,
ctx: await createContext(),
transformer: superjson,
});

2. Router externo

Este método se usa cuando no tienes acceso directo a tu router de tRPC, por ejemplo, al desarrollar una aplicación de Next.js y una API independiente alojada por separado.

ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { createServerSideHelpers } from '@trpc/react-query/server';
import type { AppRouter } from './server/router';
import superjson from 'superjson';
 
const proxyClient = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api/trpc',
}),
],
});
 
const helpers = createServerSideHelpers({
client: proxyClient,
});
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { createServerSideHelpers } from '@trpc/react-query/server';
import type { AppRouter } from './server/router';
import superjson from 'superjson';
 
const proxyClient = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api/trpc',
}),
],
});
 
const helpers = createServerSideHelpers({
client: proxyClient,
});

Uso de los helpers

Los métodos de los helpers para el lado del servidor devuelven un objeto que refleja la estructura de tu router, con todos tus routers como claves. Sin embargo, en lugar de useQuery y useMutation, obtienes las funciones prefetch, fetch, prefetchInfinite y fetchInfinite.

La diferencia principal entre prefetch y fetch es que fetch actúa como una llamada de función normal, devolviendo el resultado de la consulta, mientras que prefetch no devuelve el resultado y nunca lanza errores - si necesitas ese comportamiento, usa fetch en su lugar. En cambio, prefetch agregará la consulta a la caché, que luego deshidratas y envías al cliente.

ts
// In getServerSideProps / getStaticProps:
const props = {
// very important - use `trpcState` as the key
trpcState: helpers.dehydrate(),
};
ts
// In getServerSideProps / getStaticProps:
const props = {
// very important - use `trpcState` as the key
trpcState: helpers.dehydrate(),
};

La regla general es: usa prefetch para consultas que sabes que necesitarás en el cliente, y fetch para consultas cuyo resultado quieras usar en el servidor.

Todas estas funciones son wrappers alrededor de funciones de react-query. Consulta su documentación para aprender más en detalle.

información

Para un ejemplo completo, consult nuestro ejemplo de prueba E2E SSG

Ejemplo con Next.js

pages/posts/[id].tsx
tsx
import { createServerSideHelpers } from '@trpc/react-query/server';
import { appRouter } from './server/routers/_app';
import { trpc } from './utils/trpc';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
import superjson from 'superjson';
 
export async function getServerSideProps(
context: GetServerSidePropsContext<{ id: string }>,
) {
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {},
transformer: superjson,
});
const id = context.params?.id as string;
 
/*
* Prefetching the `post.byId` query.
* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.
*/
await helpers.post.byId.prefetch({ id });
 
// Make sure to return { props: { trpcState: helpers.dehydrate() } }
return {
props: {
trpcState: helpers.dehydrate(),
id,
},
};
}
 
export default function PostViewPage(
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) {
const { id } = props;
const postQuery = trpc.post.byId.useQuery({ id });
if (postQuery.status !== 'success') {
// won't happen since the query has been prefetched
return <>Loading...</>;
}
const { data } = postQuery;
return (
<>
<h1>{data.title}</h1>
<em>Created {data.createdAt.toLocaleDateString()}</em>
<p>{data.text}</p>
<h2>Raw data:</h2>
<pre>{JSON.stringify(data, null, 4)}</pre>
</>
);
}
pages/posts/[id].tsx
tsx
import { createServerSideHelpers } from '@trpc/react-query/server';
import { appRouter } from './server/routers/_app';
import { trpc } from './utils/trpc';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
import superjson from 'superjson';
 
export async function getServerSideProps(
context: GetServerSidePropsContext<{ id: string }>,
) {
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {},
transformer: superjson,
});
const id = context.params?.id as string;
 
/*
* Prefetching the `post.byId` query.
* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.
*/
await helpers.post.byId.prefetch({ id });
 
// Make sure to return { props: { trpcState: helpers.dehydrate() } }
return {
props: {
trpcState: helpers.dehydrate(),
id,
},
};
}
 
export default function PostViewPage(
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) {
const { id } = props;
const postQuery = trpc.post.byId.useQuery({ id });
if (postQuery.status !== 'success') {
// won't happen since the query has been prefetched
return <>Loading...</>;
}
const { data } = postQuery;
return (
<>
<h1>{data.title}</h1>
<em>Created {data.createdAt.toLocaleDateString()}</em>
<p>{data.text}</p>
<h2>Raw data:</h2>
<pre>{JSON.stringify(data, null, 4)}</pre>
</>
);
}