Hoppa till huvudinnehållet
Version: 11.x

useSubscription()

Inofficiell Beta-översättning

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

Hooken useSubscription används för att prenumerera på en subscription-procedur på servern.

Signatur

Alternativ

tips
  • Om du behöver ange alternativ men inte vill skicka någon indata kan du skicka undefined istället
  • Om du skickar skipToken från @tanstack/react-query kommer prenumerationen att pausas
  • Se vårt SSE-exempel för en komplett implementering av prenumerationer
tsx
interface UseTRPCSubscriptionOptions<TOutput, TError> {
/**
* Called when the subscription is started.
*/
onStarted?: () => void;
/**
* Called when new data is received from the subscription.
*/
onData?: (data: TOutput) => void;
/**
* Called when an **unrecoverable error** occurs and the subscription is stopped.
*/
onError?: (error: TError) => void;
/**
* Called when the subscription is completed on the server.
* The state will transition to `'idle'` with `data: undefined`.
*/
onComplete?: () => void;
/**
* @deprecated Use a `skipToken` from `@tanstack/react-query` instead.
* This will be removed in v12.
*/
enabled?: boolean;
}
tsx
interface UseTRPCSubscriptionOptions<TOutput, TError> {
/**
* Called when the subscription is started.
*/
onStarted?: () => void;
/**
* Called when new data is received from the subscription.
*/
onData?: (data: TOutput) => void;
/**
* Called when an **unrecoverable error** occurs and the subscription is stopped.
*/
onError?: (error: TError) => void;
/**
* Called when the subscription is completed on the server.
* The state will transition to `'idle'` with `data: undefined`.
*/
onComplete?: () => void;
/**
* @deprecated Use a `skipToken` from `@tanstack/react-query` instead.
* This will be removed in v12.
*/
enabled?: boolean;
}

Returtyp

Returtypen är en discriminated union baserad på status:

ts
type TRPCSubscriptionResult<TOutput, TError> =
| TRPCSubscriptionIdleResult<TOutput>
| TRPCSubscriptionConnectingResult<TOutput, TError>
| TRPCSubscriptionPendingResult<TOutput>
| TRPCSubscriptionErrorResult<TOutput, TError>;
 
interface TRPCSubscriptionIdleResult<TOutput> {
/** Subscription is disabled or has ended */
status: 'idle';
data: undefined;
error: null;
reset: () => void;
}
 
interface TRPCSubscriptionConnectingResult<TOutput, TError> {
/** Trying to establish a connection (may have a previous error from a reconnection attempt) */
status: 'connecting';
data: TOutput | undefined;
error: TError | null;
reset: () => void;
}
 
interface TRPCSubscriptionPendingResult<TOutput> {
/** Connected to the server, receiving data */
status: 'pending';
data: TOutput | undefined;
error: null;
reset: () => void;
}
 
interface TRPCSubscriptionErrorResult<TOutput, TError> {
/** An unrecoverable error occurred and the subscription is stopped */
status: 'error';
data: TOutput | undefined;
error: TError;
reset: () => void;
}
ts
type TRPCSubscriptionResult<TOutput, TError> =
| TRPCSubscriptionIdleResult<TOutput>
| TRPCSubscriptionConnectingResult<TOutput, TError>
| TRPCSubscriptionPendingResult<TOutput>
| TRPCSubscriptionErrorResult<TOutput, TError>;
 
interface TRPCSubscriptionIdleResult<TOutput> {
/** Subscription is disabled or has ended */
status: 'idle';
data: undefined;
error: null;
reset: () => void;
}
 
interface TRPCSubscriptionConnectingResult<TOutput, TError> {
/** Trying to establish a connection (may have a previous error from a reconnection attempt) */
status: 'connecting';
data: TOutput | undefined;
error: TError | null;
reset: () => void;
}
 
interface TRPCSubscriptionPendingResult<TOutput> {
/** Connected to the server, receiving data */
status: 'pending';
data: TOutput | undefined;
error: null;
reset: () => void;
}
 
interface TRPCSubscriptionErrorResult<TOutput, TError> {
/** An unrecoverable error occurred and the subscription is stopped */
status: 'error';
data: TOutput | undefined;
error: TError;
reset: () => void;
}

Exempelprocedur

server/routers/_app.ts
tsx
import EventEmitter, { on } from 'events';
import { initTRPC } from '@trpc/server';
 
export const t = initTRPC.create();
 
type Post = { id: string; title: string };
const ee = new EventEmitter();
 
export const appRouter = t.router({
onPostAdd: t.procedure.subscription(async function* (opts) {
for await (const [data] of on(ee, 'add', {
signal: opts.signal,
})) {
const post = data as Post;
yield post;
}
}),
});
 
export type AppRouter = typeof appRouter;
server/routers/_app.ts
tsx
import EventEmitter, { on } from 'events';
import { initTRPC } from '@trpc/server';
 
export const t = initTRPC.create();
 
type Post = { id: string; title: string };
const ee = new EventEmitter();
 
export const appRouter = t.router({
onPostAdd: t.procedure.subscription(async function* (opts) {
for await (const [data] of on(ee, 'add', {
signal: opts.signal,
})) {
const post = data as Post;
yield post;
}
}),
});
 
export type AppRouter = typeof appRouter;

Exempel på React-komponent

components/PostFeed.tsx
tsx
import { trpc } from '../utils/trpc';
 
type Post = { id: string; title: string };
 
export function PostFeed() {
const [posts, setPosts] = React.useState<Post[]>([]);
 
const subscription = trpc.onPostAdd.useSubscription(undefined, {
onData: (post) => {
setPosts((prev) => [...prev, post]);
},
});
 
return (
<div>
<h1>Live Feed</h1>
{subscription.status === 'connecting' && <p>Connecting...</p>}
{subscription.status === 'error' && (
<div>
<p>Error: {subscription.error.message}</p>
<button onClick={() => subscription.reset()}>Reconnect</button>
</div>
)}
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
components/PostFeed.tsx
tsx
import { trpc } from '../utils/trpc';
 
type Post = { id: string; title: string };
 
export function PostFeed() {
const [posts, setPosts] = React.useState<Post[]>([]);
 
const subscription = trpc.onPostAdd.useSubscription(undefined, {
onData: (post) => {
setPosts((prev) => [...prev, post]);
},
});
 
return (
<div>
<h1>Live Feed</h1>
{subscription.status === 'connecting' && <p>Connecting...</p>}
{subscription.status === 'error' && (
<div>
<p>Error: {subscription.error.message}</p>
<button onClick={() => subscription.reset()}>Reconnect</button>
</div>
)}
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}