Aller au contenu principal
Version : 11.x

useQuery()

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

useQuery est le hook principal pour la récupération de données. Il fonctionne similairement au useQuery de @tanstack/react-query, mais avec des options spécifiques à trpc et des fonctionnalités supplémentaires comme le streaming.

note

Pour des informations détaillées sur les options et les modèles d'utilisation, consultez la documentation TanStack Query sur les requêtes.

Signature​

tsx
declare function useQuery(
input: TInput | SkipToken,
opts?: UseTRPCQueryOptions,
): void;
 
interface UseTRPCQueryOptions
extends UseQueryOptions {
trpc: {
ssr?: boolean;
abortOnUnmount?: boolean;
context?: Record<string, unknown>;
}
}
tsx
declare function useQuery(
input: TInput | SkipToken,
opts?: UseTRPCQueryOptions,
): void;
 
interface UseTRPCQueryOptions
extends UseQueryOptions {
trpc: {
ssr?: boolean;
abortOnUnmount?: boolean;
context?: Record<string, unknown>;
}
}

Comme UseTRPCQueryOptions étend UseQueryOptions de @tanstack/react-query, vous pouvez utiliser toutes leurs options ici comme enabled, refetchOnWindowFocus, etc. Nous avons également des options spécifiques à trpc qui vous permettent d'activer ou désactiver certains comportements au niveau de chaque procédure :

  • trpc.ssr: Si vous avez ssr: true dans votre configuration globale, vous pouvez définir cette option sur false pour désactiver le SSR pour cette requête spécifique. Notez que cela ne fonctionne pas dans l'autre sens, c'est-à-dire que vous ne pouvez pas activer le SSR sur une procédure si votre configuration globale est définie sur false.

  • trpc.abortOnUnmount: Remplace la configuration globale et permet d'activer ou désactiver l'abandon des requêtes lors du démontage.

  • trpc.context: Ajoute des métadonnées supplémentaires pouvant être utilisées dans les Liens.

astuce

Si vous devez définir des options mais ne souhaitez pas transmettre d'input, vous pouvez passer undefined à la place.

Vous remarquerez que vous bénéficiez de l'auto-complétion sur l'input basée sur ce que vous avez défini dans votre schéma input côté backend.

Exemple d'utilisation​

Backend code
server/routers/_app.ts
tsx
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;
server/routers/_app.ts
tsx
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;
components/MyComponent.tsx
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>
);
}
components/MyComponent.tsx
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>
);
}

Réponses en streaming avec des générateurs asynchrones​

info

Depuis la v11, nous supportons maintenant les requêtes en streaming lors de l'utilisation du httpBatchStreamLink.

Lorsque vous retournez un générateur asynchrone dans une requête, vous allez :

  • Vous obtenez les résultats de l'itérateur dans la propriété data sous forme de tableau, qui se met à jour au fur et à mesure de la réception de la réponse

  • Le status passera à success dès la réception du premier fragment.

  • La propriété fetchStatus restera à fetching jusqu'à la réception du dernier fragment.

Exemple​

server/routers/_app.ts
tsx
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;
server/routers/_app.ts
tsx
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;
components/MyComponent.tsx
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>
);
}
components/MyComponent.tsx
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>
);
}

Propriétés du result pendant le streaming :

statusfetchStatusdata
'pending''fetching'undefined
'success''fetching'[]
'success''fetching'[0]
'success''fetching'[0, 1]
'success''fetching'[0, 1, 2]
'success''idle'[0, 1, 2]