Luke
Luke
TtRPC
Created by Luke on 8/15/2024 in #❓-help
Clarification on inconsistency between React Query + tRPC docs with serialization
Hey everyone, I have a quick question. I have been exploring using different serialization methods + learning more about tRPC / React Query as a whole. In my deep dive on the React Query docs, specifically on the Server Rendering & Hydration Serialization section, they mention that superjson is unsafe to use on the server, and recommend using devalue instead. See here, last paragraph: https://tanstack.com/query/latest/docs/framework/react/guides/ssr#serialization But then, in the tRPC docs, it actually says the opposite, almost verbatim: https://trpc.io/docs/server/data-transformers#different-transformers-for-upload-and-download Can anyone clarify for me here?
2 replies
TtRPC
Created by Luke on 7/23/2024 in #❓-help
Next.js/tRPC Prefetch w/ HydrateClient "Error occurred prerendering page"
Hello all, I'm trying to get to the bottom of an issue I'm having using prefetching with HydrateClient. I'm using the t3 stack, so I believe that HydrateClient is a helper function wrapping tRPC helpers.dehydrate()... When I run this code with pnpm dev, it works fine, but when I go to pnpm build, I am getting
Error occurred prerendering page "/queue". Read more: https://nextjs.org/docs/messages/prerender-error
Error occurred prerendering page "/queue". Read more: https://nextjs.org/docs/messages/prerender-error
Here is the minimum example that I was able to reproduce with:
// app/queue/page.tsx

import { api, HydrateClient } from "~/trpc/server";

import QueueList from "~/app/queue/components/list";

import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Queue",
};

export default function QueuePage() {
void api.queue.getList.prefetch({ status: "pending" });

return (
<HydrateClient>
<QueueList />
</HydrateClient>
);
}
// app/queue/page.tsx

import { api, HydrateClient } from "~/trpc/server";

import QueueList from "~/app/queue/components/list";

import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Queue",
};

export default function QueuePage() {
void api.queue.getList.prefetch({ status: "pending" });

return (
<HydrateClient>
<QueueList />
</HydrateClient>
);
}
And the Queue component:
// /app/queue/components/list.tsx

"use client";

import { api } from "~/trpc/react";

export default function QueueList() {
// I also get the same error with {data} = (...).useQuery
const [data] = api.queue.getList.useSuspenseQuery(
{
status: "pending",
},
{
refetchInterval: 5 * 1000,
},
);

return <h1>Test</h1>;
}
// /app/queue/components/list.tsx

"use client";

import { api } from "~/trpc/react";

export default function QueueList() {
// I also get the same error with {data} = (...).useQuery
const [data] = api.queue.getList.useSuspenseQuery(
{
status: "pending",
},
{
refetchInterval: 5 * 1000,
},
);

return <h1>Test</h1>;
}
I've tried using both useSuspenseQuery and useQuery in the client component. I'm not sure what I'm doing wrong! Would love to figure out prefetching. Relevant Versions:
"next": "^14.2.5",
"react": "^18.3.1",
"@trpc/client": "11.0.0-rc.446",
"@trpc/next": "11.0.0-rc.446",
"@trpc/react-query": "11.0.0-rc.446",
"@trpc/server": "11.0.0-rc.446"
"next": "^14.2.5",
"react": "^18.3.1",
"@trpc/client": "11.0.0-rc.446",
"@trpc/next": "11.0.0-rc.446",
"@trpc/react-query": "11.0.0-rc.446",
"@trpc/server": "11.0.0-rc.446"
4 replies
TtRPC
Created by Luke on 5/10/2024 in #❓-help
tRPC useQuery with skipToken
I am trying to implement a useQuery which only happens once. I haven't been happy with setting enabled so something like enabled: !!foo as it'll still refetch, etc (and yes I know you can disable certain refetches, but that's not the goal here). I found a supported, type-safe solution on the tRPC docs (https://trpc.io/docs/client/react/disabling-queries).
But... following their example nearly identically doesn't work for me. Broken Example
import { skipToken } from '@tanstack/react-query';
import { api } from '~/utils/trpc';

const ViewExample = () => {
const [exampleId, setExampleId] = useState<number | undefined>();
const exampleQuery = api.examples.getOne.useQuery(exampleId ? { exampleId: exampleId } : skipToken);

...
}
import { skipToken } from '@tanstack/react-query';
import { api } from '~/utils/trpc';

const ViewExample = () => {
const [exampleId, setExampleId] = useState<number | undefined>();
const exampleQuery = api.examples.getOne.useQuery(exampleId ? { exampleId: exampleId } : skipToken);

...
}
Router
getOne: protectedProcedure
.input(
z.object({
exampleId: z.number(),
}),
)
.query(async ({ ctx, input }) => {
return await ctx.apis.redacted.get<Example>(`/v1/example/${input.exampleId}`);
}),
getOne: protectedProcedure
.input(
z.object({
exampleId: z.number(),
}),
)
.query(async ({ ctx, input }) => {
return await ctx.apis.redacted.get<Example>(`/v1/example/${input.exampleId}`);
}),
And my error:
Argument of type 'unique symbol | { exampleId: number; }' is not assignable to parameter of type '{ exampleId: number; }'.
Type 'typeof skipToken' is not assignable to type '{ exampleId: number; }'.ts(2345)
Argument of type 'unique symbol | { exampleId: number; }' is not assignable to parameter of type '{ exampleId: number; }'.
Type 'typeof skipToken' is not assignable to type '{ exampleId: number; }'.ts(2345)
Am I meant to define the skipToken in the zod input? It seems counter-intuitive to have to define skipToken in the zod input every single time this needs to be used on a route. P.S. I have a feeling this is a bug on tRPC itself given how little documentation and conversation surrounds the usage of skipToken on Discord and GitHub.
4 replies