15b426d5b6
* Added realtime / react hooks examples snippet and added it to all the relevant pages * Fix link
421 lines
10 KiB
Plaintext
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 />
|