I'm trying to understand how to use the @tanstack/react-query
integration for tRPC
when I have conditional fetches that have required parameters.
For example, say I have this backend:
// Backend
export const t = initTRPC.create();
export const appRouter = t.router({
hello: t.procedure.input(
z.object({ text: z.string() })
).query((opts) => {
return {
greeting: `hello ${opts.input.text}`,
};
}),
});
Note that the text
parameter is required.
Now let's say I have this frontend:
// Frontend
export const trpc = createTRPCReact<typeof appRouter>();
function MyComponent() {
const [text, setText] = useState<string | null>(null)
const {data: helloData} = trpc.hello.useQuery({ text }) // type error
return <>
<div>{helloData.greeting}</div>
<button onClick={() => setText('a')}>a</button>
<button onClick={() => setText('b')}>b</button>
<button onClick={() => setText(null)}>none</button>
</>
}
Here text
starts as null
, and so I cannot call fetch the trpc.hello
query until it has a value. So Typescript rightly complains:
Type 'string | null' is not assignable to type 'string'.
Type 'null' is not assignable to type 'string'.(2322)
So how to do I run this query conditionally?
I can't conditionally run the query:
if (text !== null) trpc.hello.useQuery({ text }) // breaks rules of hooks
Due to the rules of hooks.
And this this:
const { data: helloData } = trpc.hello.useQuery(
{ text }, // type error, but works
{ enabled: text !== null }
)
Works at runtime, but the Typescript error is still there since it can't really know that the object is expected to be invalid when it won't be used.
So what is the right way to conditionally fetch a tRPC useQuery
?
Full code with type error in the typescript playground
It's worth noting that tRPC v11 has a new feature for this: https://trpc.io/docs/client/react/disabling-queries
But I'm stuck on v10 for the time being due to other dependencies which are not yet compatible.
for v10, you can use the bang operator:
const { data: helloData } = trpc.hello.useQuery(
{ text: text! },
{ enabled: text !== null }
)
or write your schema in the backend so that it also accepts null
, but then throws an error.
It's worth noting that tRPC v11 has a new feature for this: https://trpc.io/docs/client/react/disabling-queries
The best thing of course is to update to v11 and use the skipToken
, but you already know that :)