TanStack React Query
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
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.
Consulta rápida de ejemplo
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'}
Uso
La filosofía de este cliente es proporcionar fábricas ligeras y seguras en tipos que funcionan de forma nativa y segura con Tanstack React Query. Esto significa que simplemente siguiendo las sugerencias de autocompletado que ofrece el cliente, podrás concentrarte en desarrollar usando únicamente los conocimientos de la documentación de 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)}
El objeto trpc es completamente seguro en tipos y proporcionará autocompletado para todos los procedimientos en tu AppRouter. Al final del proxy, están disponibles los siguientes métodos:
queryOptions - consulta de datos
Disponible para todos los procedimientos de consulta. Proporciona un envoltorio seguro en tipos para la función queryOptions de Tanstack. El primer argumento es la entrada para el procedimiento, y el segundo acepta cualquier opción nativa 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,},);
Adicionalmente, puedes proporcionar un objeto trpc a la función queryOptions para pasar opciones de solicitud tRPC al cliente.
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 deseas deshabilitar una consulta de manera segura en tipos, puedes usar 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,},),);
El resultado puede pasarse a los hooks useQuery o useSuspenseQuery, o a métodos del cliente de consultas como fetchQuery, prefetchQuery, prefetchInfiniteQuery, invalidateQueries, etc.
infiniteQueryOptions - consulta de datos infinitos
Disponible para todos los procedimientos de consulta que reciben una entrada de cursor. Proporciona un envoltorio seguro en tipos para la función infiniteQueryOptions de Tanstack. El primer argumento es la entrada para el procedimiento, y el segundo acepta cualquier opción nativa 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 - obtención de la clave de consulta y operaciones en el cliente
Disponible para todos los procedimientos de consulta. Permite acceder a la clave de consulta de manera segura en tipos.
tsconst queryKey = trpc.path.to.query.queryKey();
tsconst queryKey = trpc.path.to.query.queryKey();
Como Tanstack React Query usa coincidencia aproximada para claves de consulta, también puedes crear una clave parcial para cualquier subruta que coincida con todas las consultas de un enrutador:
tsconst queryKey = trpc.router.pathKey();
tsconst queryKey = trpc.router.pathKey();
O incluso la ruta raíz para hacer coincidir todas las consultas tRPC:
tsconst queryKey = trpc.pathKey();
tsconst queryKey = trpc.pathKey();
infiniteQueryKey - obtención de la clave de consulta infinita
Disponible para todos los procedimientos de consulta que reciben una entrada de cursor. Permite acceder a la clave de consulta para consultas infinitas de manera segura en tipos.
tsconst infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({/** input */});
tsconst infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({/** input */});
El resultado puede usarse con métodos del cliente de consultas como 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 - creación de filtros de consulta
Disponible para todos los procedimientos de consulta. Permite crear filtros de consulta de manera segura en tipos.
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;},},);
Al igual que con las claves de consulta, si deseas aplicar un filtro en todo un enrutador, puedes usar pathFilter para apuntar a cualquier subruta.
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;},});
Útil para crear filtros que pueden pasarse a métodos del cliente como queryClient.invalidateQueries etc.
infiniteQueryFilter - creación de filtros para consultas infinitas
Disponible para todos los procedimientos de consulta que reciben una entrada de cursor. Permite crear filtros de consulta para consultas infinitas de manera segura en tipos.
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;},},);
Útil para crear filtros que pueden pasarse a métodos del cliente como 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 - creación de opciones de mutación
Disponible para todos los procedimientos de mutación. Proporciona una función de identificación segura en tipos para construir opciones que pueden pasarse a 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 - obtención de la clave de mutación
Disponible para todos los procedimientos de mutación. Permite obtener la clave de mutación de manera segura en tipos.
tsconst mutationKey = trpc.path.to.mutation.mutationKey();
tsconst mutationKey = trpc.path.to.mutation.mutationKey();
subscriptionOptions - creación de opciones de suscripción
TanStack no proporciona un hook de suscripción, por lo que mantenemos nuestra propia abstracción que funciona con una configuración estándar de suscripción tRPC.
Disponible para todos los procedimientos de suscripción. Proporciona una función de identificación segura en tipos para construir opciones que pueden pasarse a useSubscription.
Ten en cuenta que necesitas tener configurado en tu cliente tRPC el httpSubscriptionLink o el wsLink para usar suscripciones.
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 <>{/* ... */}</>;}
Prefijado de claves de consulta
Cuando usas múltiples proveedores de tRPC en una sola aplicación (ej. conectando a diferentes servicios backend), las consultas con la misma ruta colisionarán en la caché. Puedes evitar esto habilitando el prefijado de claves de consulta.
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
Habilita la bandera de función al crear tu contexto:
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>);}
Las claves de consulta se prefijarán correctamente para evitar colisiones:
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' }],];
Inferencia de tipos de entrada y salida
Cuando necesitas inferir los tipos de entrada y salida para un procedimiento o enrutador, hay 2 opciones disponibles según la situación.
Inferir tipos de entrada y salida de un enrutador completo
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>;
Inferir tipos para un procedimiento individual
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>;}
Acceso al cliente tRPC
Si usaste la configuración con React Context, puedes acceder al cliente tRPC usando el 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 configuraste sin React Context, puedes importar directamente la instancia global del cliente en su lugar.
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 */});