Hoppa till huvudinnehållet
Version: 11.x

TanStack React Query

Inofficiell Beta-översättning

Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →

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.

Snabbt exempel på query

tsx
import { 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'
}
tsx
import { 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'
}

Användning

Denna klients filosofi är att erbjuda tunna och typsäkra fabriker som fungerar nativt och typsäkert med Tanstack React Query. Det innebär att du genom att följa klientens autocompletes kan fokusera på att bygga med bara den kunskap som TanStack React Query-dokumentationen tillhandahåller.

tsx
export default function Basics() {
const trpc = useTRPC();
const queryClient = useQueryClient();
// Create QueryOptions which can be passed to query hooks
const myQueryOptions = trpc.path.to.query.queryOptions({ /** inputs */ })
const myQuery = useQuery(myQueryOptions)
// or:
// useSuspenseQuery(myQueryOptions)
// useInfiniteQuery(myQueryOptions)
// Create MutationOptions which can be passed to useMutation
const 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 manner
const myQueryKey = trpc.path.to.query.queryKey()
const invalidateMyQueryKey = () => {
queryClient.invalidateQueries({ queryKey: myQueryKey })
}
return (
// Your app here
)
}
tsx
export default function Basics() {
const trpc = useTRPC();
const queryClient = useQueryClient();
// Create QueryOptions which can be passed to query hooks
const myQueryOptions = trpc.path.to.query.queryOptions({ /** inputs */ })
const myQuery = useQuery(myQueryOptions)
// or:
// useSuspenseQuery(myQueryOptions)
// useInfiniteQuery(myQueryOptions)
// Create MutationOptions which can be passed to useMutation
const 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 manner
const myQueryKey = trpc.path.to.query.queryKey()
const invalidateMyQueryKey = () => {
queryClient.invalidateQueries({ queryKey: myQueryKey })
}
return (
// Your app here
)
}

trpc-objektet är helt typsäkert och kommer att ge autocompletes för alla procedurer i din AppRouter. I slutet av proxyn är följande metoder tillgängliga:

queryOptions - frågar data

Tillgänglig för alla query-procedurer. Ger ett typsäkert omslag runt Tanstacks queryOptions-funktion. Det första argumentet är input för proceduren, och det andra argumentet accepterar alla ursprungliga Tanstack React Query-alternativ.

ts
const queryOptions = trpc.path.to.query.queryOptions(
{
/** input */
},
{
// Any Tanstack React Query options
staleTime: 1000,
},
);
ts
const queryOptions = trpc.path.to.query.queryOptions(
{
/** input */
},
{
// Any Tanstack React Query options
staleTime: 1000,
},
);

Du kan dessutom tillhandahålla ett trpc-objekt till queryOptions-funktionen för att ge tRPC-begäran-alternativ till klienten.

ts
const queryOptions = trpc.path.to.query.queryOptions(
{
/** input */
},
{
trpc: {
// Provide tRPC request options to the client
context: {
// see https://trpc.io/docs/client/links#managing-context
},
},
},
);
ts
const queryOptions = trpc.path.to.query.queryOptions(
{
/** input */
},
{
trpc: {
// Provide tRPC request options to the client
context: {
// see https://trpc.io/docs/client/links#managing-context
},
},
},
);

Om du vill inaktivera en query på ett typsäkert sätt kan du använda skipToken:

ts
import { 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,
},
),
);
ts
import { 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,
},
),
);

Resultatet kan skickas till useQuery eller useSuspenseQuery hooks eller query-klientmetoder som fetchQuery, prefetchQuery, prefetchInfiniteQuery, invalidateQueries, etc.

infiniteQueryOptions - frågar oändlig data

Tillgänglig för alla query-procedurer som tar cursor-input. Ger ett typsäkert omslag runt Tanstacks infiniteQueryOptions-funktion. Det första argumentet är input för proceduren, och det andra argumentet accepterar alla ursprungliga Tanstack React Query-alternativ.

ts
const infiniteQueryOptions = trpc.path.to.query.infiniteQueryOptions(
{
/** input */
},
{
// Any Tanstack React Query options
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
},
);
ts
const infiniteQueryOptions = trpc.path.to.query.infiniteQueryOptions(
{
/** input */
},
{
// Any Tanstack React Query options
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
},
);

queryKey - hämtar query-nyckel och utför operationer på query-klienten

Tillgänglig för alla query-procedurer. Gör det möjligt att komma åt query-nyckeln på ett typsäkert sätt.

ts
const queryKey = trpc.path.to.query.queryKey();
ts
const queryKey = trpc.path.to.query.queryKey();

Eftersom Tanstack React Query använder fuzzy matching för query-nycklar kan du också skapa en partiell query-nyckel för valfri delbana för att matcha alla queries som tillhör en router:

ts
const queryKey = trpc.router.pathKey();
ts
const queryKey = trpc.router.pathKey();

Eller till och med rotbanan för att matcha alla tRPC-queries:

ts
const queryKey = trpc.pathKey();
ts
const queryKey = trpc.pathKey();

infiniteQueryKey - hämtar oändlig frågenyckel

Tillgänglig för alla query-procedurer som tar cursor-input. Gör det möjligt att komma åt frågenyckeln för en oändlig query på ett typsäkert sätt.

ts
const infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({
/** input */
});
ts
const infiniteQueryKey = trpc.path.to.query.infiniteQueryKey({
/** input */
});

Resultatet kan användas med query-klientmetoder som getQueryData, setQueryData, invalidateQueries, etc.

ts
const queryClient = useQueryClient();
// Get cached data for an infinite query
const cachedData = queryClient.getQueryData(
trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),
);
// Set cached data for an infinite query
queryClient.setQueryData(
trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),
(data) => {
// Modify the data
return data;
},
);
ts
const queryClient = useQueryClient();
// Get cached data for an infinite query
const cachedData = queryClient.getQueryData(
trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),
);
// Set cached data for an infinite query
queryClient.setQueryData(
trpc.path.to.query.infiniteQueryKey({ cursor: 0 }),
(data) => {
// Modify the data
return data;
},
);

queryFilter - skapar query-filter

Tillgänglig för alla query-procedurer. Möjliggör att skapa query-filter på ett typsäkert sätt.

ts
const queryFilter = trpc.path.to.query.queryFilter(
{
/** input */
},
{
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
},
);
ts
const queryFilter = trpc.path.to.query.queryFilter(
{
/** input */
},
{
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
},
);

Precis som med query-nycklar, om du vill köra ett filter över en hel router kan du använda pathFilter för att rikta in dig på valfri delbana.

ts
const queryFilter = trpc.path.pathFilter({
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
});
ts
const queryFilter = trpc.path.pathFilter({
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
});

Användbart för att skapa filter som kan skickas till klientmetoder som queryClient.invalidateQueries etc.

infiniteQueryFilter - skapar oändliga query-filter

Tillgänglig för alla query-procedurer som tar cursor-input. Möjliggör att skapa query-filter för oändliga queries på ett typsäkert sätt.

ts
const infiniteQueryFilter = trpc.path.to.query.infiniteQueryFilter(
{
/** input */
},
{
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
},
);
ts
const infiniteQueryFilter = trpc.path.to.query.infiniteQueryFilter(
{
/** input */
},
{
// Any Tanstack React Query filter
predicate: (query) => {
query.state.data;
},
},
);

Användbart för att skapa filter som kan skickas till klientmetoder som queryClient.invalidateQueries etc.

ts
await queryClient.invalidateQueries(
trpc.path.to.query.infiniteQueryFilter(
{},
{
predicate: (query) => {
// Filter logic based on query state
return query.state.data?.pages.length > 0;
},
},
),
);
ts
await queryClient.invalidateQueries(
trpc.path.to.query.infiniteQueryFilter(
{},
{
predicate: (query) => {
// Filter logic based on query state
return query.state.data?.pages.length > 0;
},
},
),
);

mutationOptions - skapar mutationsalternativ

Tillgänglig för alla mutationsprocedurer. Ger en typsäker identifieringsfunktion för att konstruera alternativ som kan skickas till useMutation.

ts
const mutationOptions = trpc.path.to.mutation.mutationOptions({
// Any Tanstack React Query options
onSuccess: (data) => {
// do something with the data
},
});
ts
const mutationOptions = trpc.path.to.mutation.mutationOptions({
// Any Tanstack React Query options
onSuccess: (data) => {
// do something with the data
},
});

mutationKey - hämtar mutationsnyckel

Tillgänglig för alla mutationsprocedurer. Gör det möjligt att få mutationsnyckeln på ett typsäkert sätt.

ts
const mutationKey = trpc.path.to.mutation.mutationKey();
ts
const mutationKey = trpc.path.to.mutation.mutationKey();

subscriptionOptions - skapar prenumerationsalternativ

TanStack tillhandahåller inte en prenumerations-hook, så vi fortsätter att exponera vår egen abstraktion här som fungerar med en standard tRPC-prenumerationskonfiguration. Tillgänglig för alla prenumerationsprocedurer. Ger en typsäker identifieringsfunktion för att konstruera alternativ som kan skickas till useSubscription. Observera att du måste ha antingen httpSubscriptionLink eller wsLink konfigurerad i din tRPC-klient för att använda prenumerationer.

tsx
function 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 here
subscription.data; // The lastly received data
subscription.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 <>{/* ... */}</>;
}
tsx
function 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 here
subscription.data; // The lastly received data
subscription.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 <>{/* ... */}</>;
}

Prefix för frågenyckel

När du använder flera tRPC-leverantörer i en enda applikation (t.ex. ansluter till olika backendtjänster) kan frågor med samma sökväg kollidera i cachen. Du kan förhindra detta genom att aktivera prefix för frågenyckel.

tsx
// Without prefixes - these would collide!
const authQuery = useQuery(trpcAuth.list.queryOptions()); // auth service
const billingQuery = useQuery(trpcBilling.list.queryOptions()); // billing service
tsx
// Without prefixes - these would collide!
const authQuery = useQuery(trpcAuth.list.queryOptions()); // auth service
const billingQuery = useQuery(trpcBilling.list.queryOptions()); // billing service

Aktivera funktionsflaggan när du skapar din kontext:

utils/trpc.ts
tsx
// [...]
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.ts
tsx
// [...]
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.tsx
tsx
// [...]
export function App() {
const [queryClient] = useState(() => new QueryClient());
const [billingClient] = useState(() => createBillingClient());
const [accountClient] = useState(() => createAccountClient());
return (
<QueryClientProvider client={queryClient}>
<BillingProvider
trpcClient={billingClient}
queryClient={queryClient}
keyPrefix="billing"
>
<AccountProvider
trpcClient={accountClient}
queryClient={queryClient}
keyPrefix="account"
>
{/* ... */}
</AccountProvider>
</BillingProvider>
</QueryClientProvider>
);
}
App.tsx
tsx
// [...]
export function App() {
const [queryClient] = useState(() => new QueryClient());
const [billingClient] = useState(() => createBillingClient());
const [accountClient] = useState(() => createAccountClient());
return (
<QueryClientProvider client={queryClient}>
<BillingProvider
trpcClient={billingClient}
queryClient={queryClient}
keyPrefix="billing"
>
<AccountProvider
trpcClient={accountClient}
queryClient={queryClient}
keyPrefix="account"
>
{/* ... */}
</AccountProvider>
</BillingProvider>
</QueryClientProvider>
);
}
components/MyComponent.tsx
tsx
// [...]
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.tsx
tsx
// [...]
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>
);
}

Frågenycklarna kommer att prefixas korrekt för att undvika kollisioner:

tsx
// Example of how the query keys look with prefixes
const queryKeys = [
[['billing'], ['list'], { type: 'query' }],
[['account'], ['list'], { type: 'query' }],
];
tsx
// Example of how the query keys look with prefixes
const queryKeys = [
[['billing'], ['list'], { type: 'query' }],
[['account'], ['list'], { type: 'query' }],
];

Härleda indata- och utdatatyper

När du behöver härleda indata- och utdatatyper för en procedur eller router finns det två alternativ beroende på situationen.

Härleda indata- och utdatatyper för en hel router

ts
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import { AppRouter } from './path/to/server';
export type Inputs = inferRouterInputs<AppRouter>;
export type Outputs = inferRouterOutputs<AppRouter>;
ts
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import { AppRouter } from './path/to/server';
export type Inputs = inferRouterInputs<AppRouter>;
export type Outputs = inferRouterOutputs<AppRouter>;

Härleda typer för en enskild procedur

ts
import 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>;
}
ts
import 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>;
}

Komma åt tRPC-klienten

Om du använde installation med React Context kan du komma åt tRPC-klienten med hooken useTRPCClient.

tsx
import { useTRPCClient } from './trpc';
function Component() {
const trpcClient = useTRPCClient();
const result = await trpcClient.path.to.procedure.query({
/** input */
});
}
tsx
import { useTRPCClient } from './trpc';
function Component() {
const trpcClient = useTRPCClient();
const result = await trpcClient.path.to.procedure.query({
/** input */
});
}

Om du installerade utan React Context kan du istället importera den globala klientinstansen direkt.

ts
import { client } from './trpc';
const result = await client.path.to.procedure.query({
/** input */
});
ts
import { client } from './trpc';
const result = await client.path.to.procedure.query({
/** input */
});