TanStack React Query
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 â
Compared to our classic React Query Integration this client is simpler and more TanStack Query-native, providing factories for common TanStack React Query interfaces like QueryKeys, QueryOptions, and MutationOptions. We think it's the future and recommend using this over the classic client, read the announcement post for more information about this change.
Exemple rapide de requĂȘteâ
tsximport { useQuery } from '@tanstack/react-query';import { useTRPC } from './trpc';function Users() {const trpc = useTRPC();const greetingQuery = useQuery(trpc.greeting.queryOptions({ name: 'Jerry' }));// greetingQuery.data === 'Hello Jerry'}
tsximport { useQuery } from '@tanstack/react-query';import { useTRPC } from './trpc';function Users() {const trpc = useTRPC();const greetingQuery = useQuery(trpc.greeting.queryOptions({ name: 'Jerry' }));// greetingQuery.data === 'Hello Jerry'}
Utilisationâ
La philosophie de ce client est de fournir des factories minces et typées qui fonctionnent nativement et de maniÚre type-safe avec Tanstack React Query. Cela signifie qu'en suivant simplement les autocomplétions fournies par le client, vous pouvez vous concentrer sur le développement en vous appuyant uniquement sur les connaissances des docs TanStack React Query.
tsxexport default function Basics() {const trpc = useTRPC();const queryClient = useQueryClient();// Create QueryOptions which can be passed to query hooksconst myQueryOptions = trpc.path.to.query.queryOptions({ /** inputs */ })const myQuery = useQuery(myQueryOptions)// or:// useSuspenseQuery(myQueryOptions)// useInfiniteQuery(myQueryOptions)// Create MutationOptions which can be passed to useMutationconst myMutationOptions = trpc.path.to.mutation.mutationOptions()const myMutation = useMutation(myMutationOptions)// Create a QueryKey which can be used to manipulated many methods// on TanStack's QueryClient in a type-safe mannerconst myQueryKey = trpc.path.to.query.queryKey()const invalidateMyQueryKey = () => {queryClient.invalidateQueries({ queryKey: myQueryKey })}return (// Your app here)}
tsxexport default function Basics() {const trpc = useTRPC();const queryClient = useQueryClient();// Create QueryOptions which can be passed to query hooksconst myQueryOptions = trpc.path.to.query.queryOptions({ /** inputs */ })const myQuery = useQuery(myQueryOptions)// or:// useSuspenseQuery(myQueryOptions)// useInfiniteQuery(myQueryOptions)// Create MutationOptions which can be passed to useMutationconst myMutationOptions = trpc.path.to.mutation.mutationOptions()const myMutation = useMutation(myMutationOptions)// Create a QueryKey which can be used to manipulated many methods// on TanStack's QueryClient in a type-safe mannerconst myQueryKey = trpc.path.to.query.queryKey()const invalidateMyQueryKey = () => {queryClient.invalidateQueries({ queryKey: myQueryKey })}return (// Your app here)}
L'objet trpc est entiÚrement type-safe et fournira des autocomplétions pour toutes les procédures de votre AppRouter. En fin de chaßne de proxy, les méthodes suivantes sont disponibles :
queryOptions - interrogation de donnĂ©esâ
Disponible pour toutes les procĂ©dures de requĂȘte. Fournit un wrapper type-safe autour de la fonction queryOptions de Tanstack. Le premier argument correspond Ă l'entrĂ©e de la procĂ©dure, et le second accepte toutes les options natives de Tanstack React Query.
tsconst queryOptions = trpc.path.to.query.queryOptions({/** input */},{// Any Tanstack React Query optionsstaleTime: 1000,},);
tsconst queryOptions = trpc.path.to.query.queryOptions({/** input */},{// Any Tanstack React Query optionsstaleTime: 1000,},);
Vous pouvez Ă©galement fournir un objet trpc Ă la fonction queryOptions pour transmettre des options de requĂȘte tRPC au client.
tsconst queryOptions = trpc.path.to.query.queryOptions({/** input */},{trpc: {// Provide tRPC request options to the clientcontext: {// see https://trpc.io/docs/client/links#managing-context},},},);
tsconst queryOptions = trpc.path.to.query.queryOptions({/** input */},{trpc: {// Provide tRPC request options to the clientcontext: {// see https://trpc.io/docs/client/links#managing-context},},},);
Si vous souhaitez dĂ©sactiver une requĂȘte de maniĂšre type-safe, vous pouvez utiliser skipToken :
tsimport { skipToken } from '@tanstack/react-query';const query = useQuery(trpc.user.details.queryOptions(user?.id && project?.id? {userId: user.id,projectId: project.id,}: skipToken,{staleTime: 1000,},),);
tsimport { skipToken } from '@tanstack/react-query';const query = useQuery(trpc.user.details.queryOptions(user?.id && project?.id? {userId: user.id,projectId: project.id,}: skipToken,{staleTime: 1000,},),);
Le rĂ©sultat peut ĂȘtre passĂ© aux hooks useQuery ou useSuspenseQuery, ou aux mĂ©thodes du client de requĂȘte comme fetchQuery, prefetchQuery, prefetchInfiniteQuery, invalidateQueries, etc.
infiniteQueryOptions - interrogation de donnĂ©es infiniesâ
Disponible pour toutes les procĂ©dures de requĂȘte acceptant une entrĂ©e de curseur. Fournit un wrapper type-safe autour de la fonction infiniteQueryOptions de Tanstack. Le premier argument correspond Ă l'entrĂ©e de la procĂ©dure, et le second accepte toutes les options natives de Tanstack React Query.
tsconst infiniteQueryOptions = trpc.path.to.query.infiniteQueryOptions({/** input */},{// Any Tanstack React Query optionsgetNextPageParam: (lastPage, pages) => lastPage.nextCursor,},);
tsconst infiniteQueryOptions = trpc.path.to.query.infiniteQueryOptions({/** input */},{// Any Tanstack React Query optionsgetNextPageParam: (lastPage, pages) => lastPage.nextCursor,},);
queryKey - obtention de la clĂ© de requĂȘte et opĂ©rations sur le client de requĂȘteâ
Disponible pour toutes les procĂ©dures de requĂȘte. Permet d'accĂ©der Ă la clĂ© de requĂȘte de maniĂšre type-safe.
tsconst queryKey = trpc.path.to.query.queryKey();
tsconst queryKey = trpc.path.to.query.queryKey();
Comme Tanstack React Query utilise un matching flou pour les clĂ©s de requĂȘte, vous pouvez Ă©galement crĂ©er une clĂ© de requĂȘte partielle pour tout sous-chemin afin de correspondre Ă toutes les requĂȘtes d'un routeur :
tsconst queryKey = trpc.router.pathKey();
tsconst queryKey = trpc.router.pathKey();
Ou mĂȘme le chemin racine pour correspondre Ă toutes les requĂȘtes tRPC :
tsconst queryKey = trpc.pathKey();
tsconst queryKey = trpc.pathKey();
infiniteQueryKey - obtention de la clĂ© de requĂȘte infinieâ
Disponible pour toutes les procĂ©dures de requĂȘte acceptant une entrĂ©e de curseur. Permet d'accĂ©der Ă la clĂ© de requĂȘte pour une requĂȘte infinie de maniĂšre type-safe.
tsconst infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({/** input */});
tsconst infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({/** input */});
Le rĂ©sultat peut ĂȘtre utilisĂ© avec des mĂ©thodes du client de requĂȘte telles que getQueryData, setQueryData, invalidateQueries, etc.
tsconst queryClient = useQueryClient();// Get cached data for an infinite queryconst cachedData = queryClient.getQueryData(trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),);// Set cached data for an infinite queryqueryClient.setQueryData(trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),(data) => {// Modify the datareturn data;},);
tsconst queryClient = useQueryClient();// Get cached data for an infinite queryconst cachedData = queryClient.getQueryData(trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),);// Set cached data for an infinite queryqueryClient.setQueryData(trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),(data) => {// Modify the datareturn data;},);
queryFilter - crĂ©ation de filtres de requĂȘteâ
Disponible pour toutes les procĂ©dures de requĂȘte. Permet de crĂ©er des filtres de requĂȘte de maniĂšre type-safe.
tsconst queryFilter = trpc.path.to.query.queryFilter({/** input */},{// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},},);
tsconst queryFilter = trpc.path.to.query.queryFilter({/** input */},{// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},},);
Comme pour les clĂ©s de requĂȘte, si vous souhaitez appliquer un filtre sur un routeur entier, vous pouvez utiliser pathFilter pour cibler n'importe quel sous-chemin.
tsconst queryFilter = trpc.path.pathFilter({// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},});
tsconst queryFilter = trpc.path.pathFilter({// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},});
Utile pour crĂ©er des filtres pouvant ĂȘtre passĂ©s aux mĂ©thodes client comme queryClient.invalidateQueries, etc.
infiniteQueryFilter - crĂ©ation de filtres de requĂȘte infinieâ
Disponible pour toutes les procĂ©dures de requĂȘte acceptant une entrĂ©e de curseur. Permet de crĂ©er des filtres de requĂȘte pour les requĂȘtes infinies de maniĂšre type-safe.
tsconst infiniteQueryFilter = trpc.path.to.query.infiniteQueryFilter({/** input */},{// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},},);
tsconst infiniteQueryFilter = trpc.path.to.query.infiniteQueryFilter({/** input */},{// Any Tanstack React Query filterpredicate: (query) => {query.state.data;},},);
Utile pour crĂ©er des filtres pouvant ĂȘtre passĂ©s aux mĂ©thodes client comme queryClient.invalidateQueries, etc.
tsawait queryClient.invalidateQueries(trpc.path.to.query.infiniteQueryFilter({},{predicate: (query) => {// Filter logic based on query statereturn query.state.data?.pages.length > 0;},},),);
tsawait queryClient.invalidateQueries(trpc.path.to.query.infiniteQueryFilter({},{predicate: (query) => {// Filter logic based on query statereturn query.state.data?.pages.length > 0;},},),);
mutationOptions - crĂ©ation d'options de mutationâ
Disponible pour toutes les procĂ©dures de mutation. Fournit une fonction d'identification type-safe pour construire des options pouvant ĂȘtre passĂ©es Ă useMutation.
tsconst mutationOptions = trpc.path.to.mutation.mutationOptions({// Any Tanstack React Query optionsonSuccess: (data) => {// do something with the data},});
tsconst mutationOptions = trpc.path.to.mutation.mutationOptions({// Any Tanstack React Query optionsonSuccess: (data) => {// do something with the data},});
mutationKey - obtention de la clĂ© de mutationâ
Disponible pour toutes les procédures de mutation. Permet d'obtenir la clé de mutation de maniÚre type-safe.
tsconst mutationKey = trpc.path.to.mutation.mutationKey();
tsconst mutationKey = trpc.path.to.mutation.mutationKey();
subscriptionOptions - crĂ©ation d'options d'abonnementâ
TanStack ne fournit pas de hook d'abonnement, nous exposons donc ici notre propre abstraction qui fonctionne avec une configuration standard d'abonnement tRPC.
Disponible pour toutes les procĂ©dures d'abonnement. Fournit une fonction d'identification type-safe pour construire des options pouvant ĂȘtre passĂ©es Ă useSubscription.
Notez que vous devez avoir configuré soit le httpSubscriptionLink soit le wsLink dans votre client tRPC pour utiliser les abonnements.
tsxfunction SubscriptionExample() {const trpc = useTRPC();const subscription = useSubscription(trpc.path.to.subscription.subscriptionOptions({/** input */},{enabled: true,onStarted: () => {// do something when the subscription is started},onData: (data) => {// you can handle the data here},onError: (error) => {// you can handle the error here},onConnectionStateChange: (state) => {// you can handle the connection state here},},),);// Or you can handle the state heresubscription.data; // The lastly received datasubscription.error; // The lastly received error/*** The current status of the subscription.* Will be one of: `'idle'`, `'connecting'`, `'pending'`, or `'error'`.** - `idle`: subscription is disabled or ended* - `connecting`: trying to establish a connection* - `pending`: connected to the server, receiving data* - `error`: an error occurred and the subscription is stopped*/subscription.status;// Reset the subscription (if you have an error etc)subscription.reset();return <>{/* ... */}</>;}
tsxfunction SubscriptionExample() {const trpc = useTRPC();const subscription = useSubscription(trpc.path.to.subscription.subscriptionOptions({/** input */},{enabled: true,onStarted: () => {// do something when the subscription is started},onData: (data) => {// you can handle the data here},onError: (error) => {// you can handle the error here},onConnectionStateChange: (state) => {// you can handle the connection state here},},),);// Or you can handle the state heresubscription.data; // The lastly received datasubscription.error; // The lastly received error/*** The current status of the subscription.* Will be one of: `'idle'`, `'connecting'`, `'pending'`, or `'error'`.** - `idle`: subscription is disabled or ended* - `connecting`: trying to establish a connection* - `pending`: connected to the server, receiving data* - `error`: an error occurred and the subscription is stopped*/subscription.status;// Reset the subscription (if you have an error etc)subscription.reset();return <>{/* ... */}</>;}
PrĂ©fixage des clĂ©s de requĂȘteâ
Lorsque vous utilisez plusieurs clients tRPC dans une mĂȘme application (par ex. pour vous connecter Ă diffĂ©rents services backend), les requĂȘtes ayant le mĂȘme chemin entreront en conflit dans le cache. Vous pouvez Ă©viter cela en activant le prĂ©fixage des clĂ©s de requĂȘte.
tsx// Without prefixes - these would collide!const authQuery = useQuery(trpcAuth.list.queryOptions()); // auth serviceconst billingQuery = useQuery(trpcBilling.list.queryOptions()); // billing service
tsx// Without prefixes - these would collide!const authQuery = useQuery(trpcAuth.list.queryOptions()); // auth serviceconst billingQuery = useQuery(trpcBilling.list.queryOptions()); // billing service
Activez le feature flag lors de la création de votre contexte :
utils/trpc.tstsx// [...]const billing = createTRPCContext<BillingRouter, { keyPrefix: true }>();export const BillingProvider = billing.TRPCProvider;export const useBilling = billing.useTRPC;export const createBillingClient = () =>createTRPCClient<BillingRouter>({links: [/* ... */],});const account = createTRPCContext<AccountRouter, { keyPrefix: true }>();export const AccountProvider = account.TRPCProvider;export const useAccount = account.useTRPC;export const createAccountClient = () =>createTRPCClient<AccountRouter>({links: [/* ... */],});
utils/trpc.tstsx// [...]const billing = createTRPCContext<BillingRouter, { keyPrefix: true }>();export const BillingProvider = billing.TRPCProvider;export const useBilling = billing.useTRPC;export const createBillingClient = () =>createTRPCClient<BillingRouter>({links: [/* ... */],});const account = createTRPCContext<AccountRouter, { keyPrefix: true }>();export const AccountProvider = account.TRPCProvider;export const useAccount = account.useTRPC;export const createAccountClient = () =>createTRPCClient<AccountRouter>({links: [/* ... */],});
App.tsxtsx// [...]export function App() {const [queryClient] = useState(() => new QueryClient());const [billingClient] = useState(() => createBillingClient());const [accountClient] = useState(() => createAccountClient());return (<QueryClientProvider client={queryClient}><BillingProvidertrpcClient={billingClient}queryClient={queryClient}keyPrefix="billing"><AccountProvidertrpcClient={accountClient}queryClient={queryClient}keyPrefix="account">{/* ... */}</AccountProvider></BillingProvider></QueryClientProvider>);}
App.tsxtsx// [...]export function App() {const [queryClient] = useState(() => new QueryClient());const [billingClient] = useState(() => createBillingClient());const [accountClient] = useState(() => createAccountClient());return (<QueryClientProvider client={queryClient}><BillingProvidertrpcClient={billingClient}queryClient={queryClient}keyPrefix="billing"><AccountProvidertrpcClient={accountClient}queryClient={queryClient}keyPrefix="account">{/* ... */}</AccountProvider></BillingProvider></QueryClientProvider>);}
components/MyComponent.tsxtsx// [...]export function MyComponent() {const billing = useBilling();const account = useAccount();const billingList = useQuery(billing.list.queryOptions());const accountList = useQuery(account.list.queryOptions());return (<div><div>Billing: {JSON.stringify(billingList.data ?? null)}</div><div>Account: {JSON.stringify(accountList.data ?? null)}</div></div>);}
components/MyComponent.tsxtsx// [...]export function MyComponent() {const billing = useBilling();const account = useAccount();const billingList = useQuery(billing.list.queryOptions());const accountList = useQuery(account.list.queryOptions());return (<div><div>Billing: {JSON.stringify(billingList.data ?? null)}</div><div>Account: {JSON.stringify(accountList.data ?? null)}</div></div>);}
Les clĂ©s de requĂȘte seront correctement prĂ©fixĂ©es pour Ă©viter les collisions :
tsx// Example of how the query keys look with prefixesconstqueryKeys = [[['billing'], ['list'], {type : 'query' }],[['account'], ['list'], {type : 'query' }],];
tsx// Example of how the query keys look with prefixesconstqueryKeys = [[['billing'], ['list'], {type : 'query' }],[['account'], ['list'], {type : 'query' }],];
InfĂ©rer les types d'entrĂ©e et de sortieâ
Lorsque vous devez inférer les types d'entrée et de sortie pour une procédure ou un routeur, deux options sont disponibles selon la situation.
Inférer les types d'entrée et de sortie d'un routeur complet
tsimport type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';import { AppRouter } from './path/to/server';export type Inputs = inferRouterInputs<AppRouter>;export type Outputs = inferRouterOutputs<AppRouter>;
tsimport type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';import { AppRouter } from './path/to/server';export type Inputs = inferRouterInputs<AppRouter>;export type Outputs = inferRouterOutputs<AppRouter>;
Inférer les types pour une procédure individuelle
tsimport type { inferInput, inferOutput } from '@trpc/tanstack-react-query';function Component() {const trpc = useTRPC();type Input = inferInput<typeof trpc.path.to.procedure>;type Output = inferOutput<typeof trpc.path.to.procedure>;}
tsimport type { inferInput, inferOutput } from '@trpc/tanstack-react-query';function Component() {const trpc = useTRPC();type Input = inferInput<typeof trpc.path.to.procedure>;type Output = inferOutput<typeof trpc.path.to.procedure>;}
AccĂ©der au client tRPCâ
Si vous avez utilisé la configuration avec le contexte React, vous pouvez accéder au client tRPC via le hook useTRPCClient.
tsximport { useTRPCClient } from './trpc';function Component() {const trpcClient = useTRPCClient();const result = await trpcClient.path.to.procedure.query({/** input */});}
tsximport { useTRPCClient } from './trpc';function Component() {const trpcClient = useTRPCClient();const result = await trpcClient.path.to.procedure.query({/** input */});}
Si vous avez configuré sans contexte React, vous pouvez importer directement l'instance client globale.
tsimport { client } from './trpc';const result = await client.path.to.procedure.query({/** input */});
tsimport { client } from './trpc';const result = await client.path.to.procedure.query({/** input */});