Files
Dan 15b426d5b6 Add realtime / react hooks examples snippet (#1770)
* Added realtime / react hooks examples snippet and added it to all the relevant pages

* Fix link
2025-03-28 15:57:41 +00:00

421 lines
10 KiB
Plaintext

---
title: Realtime hooks
sidebarTitle: Realtime
description: Get live updates from the Trigger.dev API in your frontend application.
---
import RealtimeExamplesCards from "/snippets/realtime-examples-cards.mdx";
These hooks allow you to subscribe to runs, batches, and streams using [Trigger.dev realtime](/realtime). Before reading this guide:
- Read our [Realtime documentation](/realtime) to understand how the Trigger.dev realtime API works.
- Read how to [setup and authenticate](/frontend/overview) using the `@trigger.dev/react-hooks` package.
## Hooks
### useRealtimeRun
The `useRealtimeRun` hook allows you to subscribe to a run by its ID.
```tsx
"use client"; // This is needed for Next.js App Router or other RSC frameworks
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
return <div>Run: {run.id}</div>;
}
```
To correctly type the run's payload and output, you can provide the type of your task to the `useRealtimeRun` hook:
```tsx
import { useRealtimeRun } from "@trigger.dev/react-hooks";
import type { myTask } from "@/trigger/myTask";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, error } = useRealtimeRun<typeof myTask>(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
// Now run.payload and run.output are correctly typed
return <div>Run: {run.id}</div>;
}
```
You can supply an `onComplete` callback to the `useRealtimeRun` hook to be called when the run is completed or errored. This is useful if you want to perform some action when the run is completed, like navigating to a different page or showing a notification.
```tsx
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
onComplete: (run, error) => {
console.log("Run completed", run);
},
});
if (error) return <div>Error: {error.message}</div>;
return <div>Run: {run.id}</div>;
}
```
See our [Realtime documentation](/realtime) for more information about the type of the run object and more.
### useRealtimeRunsWithTag
The `useRealtimeRunsWithTag` hook allows you to subscribe to multiple runs with a specific tag.
```tsx
"use client"; // This is needed for Next.js App Router or other RSC frameworks
import { useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";
export function MyComponent({ tag }: { tag: string }) {
const { runs, error } = useRealtimeRunsWithTag(tag);
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{runs.map((run) => (
<div key={run.id}>Run: {run.id}</div>
))}
</div>
);
}
```
To correctly type the runs payload and output, you can provide the type of your task to the `useRealtimeRunsWithTag` hook:
```tsx
import { useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";
import type { myTask } from "@/trigger/myTask";
export function MyComponent({ tag }: { tag: string }) {
const { runs, error } = useRealtimeRunsWithTag<typeof myTask>(tag);
if (error) return <div>Error: {error.message}</div>;
// Now runs[i].payload and runs[i].output are correctly typed
return (
<div>
{runs.map((run) => (
<div key={run.id}>Run: {run.id}</div>
))}
</div>
);
}
```
If `useRealtimeRunsWithTag` could return multiple different types of tasks, you can pass a union of all the task types to the hook:
```tsx
import { useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";
import type { myTask1, myTask2 } from "@/trigger/myTasks";
export function MyComponent({ tag }: { tag: string }) {
const { runs, error } = useRealtimeRunsWithTag<typeof myTask1 | typeof myTask2>(tag);
if (error) return <div>Error: {error.message}</div>;
// You can narrow down the type of the run based on the taskIdentifier
for (const run of runs) {
if (run.taskIdentifier === "my-task-1") {
// run is correctly typed as myTask1
} else if (run.taskIdentifier === "my-task-2") {
// run is correctly typed as myTask2
}
}
return (
<div>
{runs.map((run) => (
<div key={run.id}>Run: {run.id}</div>
))}
</div>
);
}
```
### useRealtimeBatch
The `useRealtimeBatch` hook allows you to subscribe to a batch of runs by its the batch ID.
```tsx
"use client"; // This is needed for Next.js App Router or other RSC frameworks
import { useRealtimeBatch } from "@trigger.dev/react-hooks";
export function MyComponent({ batchId }: { batchId: string }) {
const { runs, error } = useRealtimeBatch(batchId);
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{runs.map((run) => (
<div key={run.id}>Run: {run.id}</div>
))}
</div>
);
}
```
See our [Realtime documentation](/realtime) for more information.
### useRealtimeRunWithStreams
The `useRealtimeRunWithStreams` hook allows you to subscribe to a run by its ID and also receive any streams that are emitted by the task. See our [Realtime documentation](/realtime#streams) for more information about emitting streams from a task.
```tsx
"use client"; // This is needed for Next.js App Router or other RSC frameworks
import { useRealtimeRunWithStreams } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, streams, error } = useRealtimeRunWithStreams(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<div>Run: {run.id}</div>
<div>
{Object.keys(streams).map((stream) => (
<div key={stream}>Stream: {stream}</div>
))}
</div>
</div>
);
}
```
You can provide the type of the streams to the `useRealtimeRunWithStreams` hook:
```tsx
import { useRealtimeRunWithStreams } from "@trigger.dev/react-hooks";
import type { myTask } from "@/trigger/myTask";
type STREAMS = {
openai: string; // this is the type of each "part" of the stream
};
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, streams, error } = useRealtimeRunWithStreams<typeof myTask, STREAMS>(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
const text = streams.openai?.map((part) => part).join("");
return (
<div>
<div>Run: {run.id}</div>
<div>{text}</div>
</div>
);
}
```
As you can see above, each stream is an array of the type you provided, keyed by the stream name. If instead of a pure text stream you have a stream of objects, you can provide the type of the object:
```tsx
import type { TextStreamPart } from "ai";
import type { myTask } from "@/trigger/myTask";
type STREAMS = { openai: TextStreamPart<{}> };
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, streams, error } = useRealtimeRunWithStreams<typeof myTask, STREAMS>(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
const text = streams.openai
?.filter((stream) => stream.type === "text-delta")
?.map((part) => part.text)
.join("");
return (
<div>
<div>Run: {run.id}</div>
<div>{text}</div>
</div>
);
}
```
## Common options
### accessToken & baseURL
You can pass the `accessToken` option to the Realtime hooks to authenticate the subscription.
```tsx
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
baseURL: "https://my-self-hosted-trigger.com", // Optional if you are using a self-hosted Trigger.dev instance
});
if (error) return <div>Error: {error.message}</div>;
return <div>Run: {run.id}</div>;
}
```
### enabled
You can pass the `enabled` option to the Realtime hooks to enable or disable the subscription.
```tsx
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
enabled,
}: {
runId: string;
publicAccessToken: string;
enabled: boolean;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
enabled,
});
if (error) return <div>Error: {error.message}</div>;
return <div>Run: {run.id}</div>;
}
```
This allows you to conditionally disable using the hook based on some state.
### id
You can pass the `id` option to the Realtime hooks to change the ID of the subscription.
```tsx
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function MyComponent({
id,
runId,
publicAccessToken,
enabled,
}: {
id: string;
runId: string;
publicAccessToken: string;
enabled: boolean;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
enabled,
id,
});
if (error) return <div>Error: {error.message}</div>;
return <div>Run: {run.id}</div>;
}
```
This allows you to change the ID of the subscription based on some state. Passing in a different ID will unsubscribe from the current subscription and subscribe to the new one (and remove any cached data).
### experimental_throttleInMs
The `*withStreams` variants of the Realtime hooks accept an `experimental_throttleInMs` option to throttle the updates from the server. This can be useful if you are getting too many updates and want to reduce the number of updates.
```tsx
import { useRealtimeRunsWithStreams } from "@trigger.dev/react-hooks";
export function MyComponent({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { runs, error } = useRealtimeRunsWithStreams(tag, {
accessToken: publicAccessToken,
experimental_throttleInMs: 1000, // Throttle updates to once per second
});
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{runs.map((run) => (
<div key={run.id}>Run: {run.id}</div>
))}
</div>
);
}
```
<RealtimeExamplesCards />