UNPKG

@trpc/next

Version:

The tRPC Next.js library

161 lines (122 loc) • 5.04 kB
# useQuery() > Fetch data with the classic trpc.procedure.useQuery() hook, its tRPC-specific options and streaming From https://trpc.io/docs/client/react/useQuery `useQuery` is the primary hook for data fetching, it works similarly to `@tanstack/react-query`'s `useQuery`, but with some `trpc` specific options and additional features like streaming. > [!NOTE] > For in-depth information about options and usage patterns, refer to the TanStack Query docs on [queries](https://tanstack.com/query/v5/docs/framework/react/guides/queries). ## Signature ```tsx no-check declare function useQuery( input: TInput | SkipToken, opts?: UseTRPCQueryOptions, ): void; interface UseTRPCQueryOptions extends UseQueryOptions { trpc: { ssr?: boolean; abortOnUnmount?: boolean; context?: Record<string, unknown>; } } ``` Since `UseTRPCQueryOptions` extends `@tanstack/react-query`'s `UseQueryOptions`, you can use any of their options here such as `enabled`, `refetchOnWindowFocus`, etc. We also have some `trpc` specific options that let you opt in or out of certain behaviors on a per-procedure level: - **`trpc.ssr`:** If you have `ssr: true` in your [global config](https://trpc.io/docs/client/nextjs/pages-router/setup#ssr-boolean-default-false), you can set this to false to disable ssr for this particular query. _Note that this does not work the other way around, i.e., you can not enable ssr on a procedure if your global config is set to false._ - **`trpc.abortOnUnmount`:** Override the [global config](https://trpc.io/docs/client/nextjs/pages-router/setup#config-callback) and opt in or out of aborting queries on unmount. - **`trpc.context`:** Add extra meta data that could be used in [Links](https://trpc.io/docs/client/links). > [!TIP] > If you need to set any options but don't want to pass any input, you can pass `undefined` instead. You'll notice that you get autocompletion on the `input` based on what you have set in your `input` schema on your backend. ## Example usage <details> <summary>Backend code</summary> ```tsx no-check title="server/routers/_app.ts" import { initTRPC } from '@trpc/server'; import { z } from 'zod'; export const t = initTRPC.create(); export const appRouter = t.router({ // Create procedure at path 'hello' hello: t.procedure // using zod schema to validate and infer input values .input( z .object({ text: z.string().nullish(), }) .nullish(), ) .query((opts) => { return { greeting: `hello ${opts.input?.text ?? 'world'}`, }; }), }); export type AppRouter = typeof appRouter; ``` </details> ```tsx no-check title="components/MyComponent.tsx" import { trpc } from '../utils/trpc'; export function MyComponent() { // input is optional, so we don't have to pass second argument const helloNoArgs = trpc.hello.useQuery(); const helloWithArgs = trpc.hello.useQuery({ text: 'client' }); return ( <div> <h1>Hello World Example</h1> <ul> <li> helloNoArgs ({helloNoArgs.status}):{' '} <pre>{JSON.stringify(helloNoArgs.data, null, 2)}</pre> </li> <li> helloWithArgs ({helloWithArgs.status}):{' '} <pre>{JSON.stringify(helloWithArgs.data, null, 2)}</pre> </li> </ul> </div> ); } ``` ## Streaming responses using async generators > [!NOTE] Info > Since v11 we now support streaming queries when using the [`httpBatchStreamLink`](https://trpc.io/docs/client/links/httpBatchStreamLink#generators). When returning an async generator in a query, you will: - Get the results of the iterator in the `data`-property **as an array** which updates as the response comes in - The `status` will be `success` as soon as the first chunk is received. - The `fetchStatus` property which will be `fetching` until the last chunk is received. ### Example ```tsx no-check title="server/routers/_app.ts" import { initTRPC } from '@trpc/server'; const t = initTRPC.create(); const appRouter = t.router({ iterable: t.procedure.query(async function* () { for (let i = 0; i < 3; i++) { await new Promise((resolve) => setTimeout(resolve, 500)); yield i; } }), }); export type AppRouter = typeof appRouter; ``` ```tsx no-check title="components/MyComponent.tsx" import React, { Fragment } from 'react'; import { trpc } from '../utils/trpc'; export function MyComponent() { const result = trpc.iterable.useQuery(); return ( <div> {result.data?.map((chunk, index) => ( <Fragment key={index}>{chunk}</Fragment> ))} </div> ); } ``` `result` properties while streaming: | `status` | `fetchStatus` | `data` | | ----------- | ------------- | ----------- | | `'pending'` | `'fetching'` | `undefined` | | `'success'` | `'fetching'` | `[]` | | `'success'` | `'fetching'` | `[0]` | | `'success'` | `'fetching'` | `[0, 1]` | | `'success'` | `'fetching'` | `[0, 1, 2]` | | `'success'` | `'idle'` | `[0, 1, 2]` |