c37622e7b6
* JWT scopes for tags and batches can now access runs that have the tag or are in the batch - useTaskTrigger can now submit options - auto-generated batch trigger public access tokens no longer need each individual run ID scope * Add changeset * Added task scopes to work like tags and batches Also removed scopes for tags when auto-generating a public access token as that could be dangerous.
798 lines
21 KiB
Plaintext
798 lines
21 KiB
Plaintext
---
|
|
title: React hooks
|
|
sidebarTitle: React hooks
|
|
description: Using the Trigger.dev v3 API from your React application.
|
|
---
|
|
|
|
Our react hooks package provides a set of hooks that make it easy to interact with the Trigger.dev API from your React application, using our [frontend API](/frontend/overview). You can use these hooks to fetch runs, batches, and subscribe to real-time updates.
|
|
|
|
## Installation
|
|
|
|
Install the `@trigger.dev/react-hooks` package in your project:
|
|
|
|
<CodeGroup>
|
|
|
|
```bash npm
|
|
npm add @trigger.dev/react-hooks
|
|
```
|
|
|
|
```bash pnpm
|
|
pnpm add @trigger.dev/react-hooks
|
|
```
|
|
|
|
```bash yarn
|
|
yarn install @trigger.dev/react-hooks
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
## Authentication
|
|
|
|
All hooks accept an optional last argument `options` that accepts an `accessToken` param, which should be a valid Public Access Token. Learn more about [generating tokens in the frontend guide](/frontend/overview).
|
|
|
|
```tsx
|
|
import { useRealtimeRun } from "@trigger.dev/react-hooks";
|
|
|
|
export function MyComponent({
|
|
runId,
|
|
publicAccessToken,
|
|
}: {
|
|
runId: string;
|
|
publicAccessToken: string;
|
|
}) {
|
|
const { run, error } = useRealtimeRun(runId, {
|
|
accessToken: publicAccessToken, // This is required
|
|
baseURL: "https://your-trigger-dev-instance.com", // optional, only needed if you are self-hosting Trigger.dev
|
|
});
|
|
|
|
// ...
|
|
}
|
|
```
|
|
|
|
Alternatively, you can use our `TriggerAuthContext` provider
|
|
|
|
```tsx
|
|
import { TriggerAuthContext } from "@trigger.dev/react-hooks";
|
|
|
|
export function SetupTrigger({ publicAccessToken }: { publicAccessToken: string }) {
|
|
return (
|
|
<TriggerAuthContext.Provider value={{ accessToken: publicAccessToken }}>
|
|
<MyComponent />
|
|
</TriggerAuthContext.Provider>
|
|
);
|
|
}
|
|
```
|
|
|
|
Now children components can use the hooks to interact with the Trigger.dev API. If you are self-hosting Trigger.dev, you can provide the `baseURL` to the `TriggerAuthContext` provider.
|
|
|
|
```tsx
|
|
import { TriggerAuthContext } from "@trigger.dev/react-hooks";
|
|
|
|
export function SetupTrigger({ publicAccessToken }: { publicAccessToken: string }) {
|
|
return (
|
|
<TriggerAuthContext.Provider
|
|
value={{
|
|
accessToken: publicAccessToken,
|
|
baseURL: "https://your-trigger-dev-instance.com",
|
|
}}
|
|
>
|
|
<MyComponent />
|
|
</TriggerAuthContext.Provider>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Next.js and client components
|
|
|
|
If you are using Next.js with the App Router, you have to make sure the component that uses the `TriggerAuthContext` is a client component. So for example, the following code will not work:
|
|
|
|
```tsx app/page.tsx
|
|
import { TriggerAuthContext } from "@trigger.dev/react-hooks";
|
|
|
|
export default function Page() {
|
|
return (
|
|
<TriggerAuthContext.Provider value={{ accessToken: "your-access-token" }}>
|
|
<MyComponent />
|
|
</TriggerAuthContext.Provider>
|
|
);
|
|
}
|
|
```
|
|
|
|
That's because `Page` is a server component and the `TriggerAuthContext.Provider` uses client-only react code. To fix this, wrap the `TriggerAuthContext.Provider` in a client component:
|
|
|
|
```ts components/TriggerProvider.tsx
|
|
"use client";
|
|
|
|
import { TriggerAuthContext } from "@trigger.dev/react-hooks";
|
|
|
|
export function TriggerProvider({
|
|
accessToken,
|
|
children,
|
|
}: {
|
|
accessToken: string;
|
|
children: React.ReactNode;
|
|
}) {
|
|
return (
|
|
<TriggerAuthContext.Provider
|
|
value={{
|
|
accessToken,
|
|
}}
|
|
>
|
|
{children}
|
|
</TriggerAuthContext.Provider>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Passing the token to the frontend
|
|
|
|
Techniques for passing the token to the frontend vary depending on your setup. Here are a few ways to do it for different setups:
|
|
|
|
#### Next.js App Router
|
|
|
|
If you are using Next.js with the App Router and you are triggering a task from a server action, you can use cookies to store and pass the token to the frontend.
|
|
|
|
```tsx actions/trigger.ts
|
|
"use server";
|
|
|
|
import { tasks } from "@trigger.dev/sdk/v3";
|
|
import type { exampleTask } from "@/trigger/example";
|
|
import { redirect } from "next/navigation";
|
|
import { cookies } from "next/headers";
|
|
|
|
export async function startRun() {
|
|
const handle = await tasks.trigger<typeof exampleTask>("example", { foo: "bar" });
|
|
|
|
// Set the auto-generated publicAccessToken in a cookie
|
|
cookies().set("publicAccessToken", handle.publicAccessToken); // ✅ this token only has access to read this run
|
|
|
|
redirect(`/runs/${handle.id}`);
|
|
}
|
|
```
|
|
|
|
Then in the `/runs/[id].tsx` page, you can read the token from the cookie and pass it to the `TriggerProvider`.
|
|
|
|
```tsx pages/runs/[id].tsx
|
|
import { TriggerProvider } from "@/components/TriggerProvider";
|
|
|
|
export default function RunPage({ params }: { params: { id: string } }) {
|
|
const publicAccessToken = cookies().get("publicAccessToken");
|
|
|
|
return (
|
|
<TriggerProvider accessToken={publicAccessToken}>
|
|
<RunDetails id={params.id} />
|
|
</TriggerProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
Instead of a cookie, you could also use a query parameter to pass the token to the frontend:
|
|
|
|
```tsx actions/trigger.ts
|
|
import { tasks } from "@trigger.dev/sdk/v3";
|
|
import type { exampleTask } from "@/trigger/example";
|
|
import { redirect } from "next/navigation";
|
|
import { cookies } from "next/headers";
|
|
|
|
export async function startRun() {
|
|
const handle = await tasks.trigger<typeof exampleTask>("example", { foo: "bar" });
|
|
|
|
redirect(`/runs/${handle.id}?publicAccessToken=${handle.publicAccessToken}`);
|
|
}
|
|
```
|
|
|
|
And then in the `/runs/[id].tsx` page:
|
|
|
|
```tsx pages/runs/[id].tsx
|
|
import { TriggerProvider } from "@/components/TriggerProvider";
|
|
|
|
export default function RunPage({
|
|
params,
|
|
searchParams,
|
|
}: {
|
|
params: { id: string };
|
|
searchParams: { publicAccessToken: string };
|
|
}) {
|
|
return (
|
|
<TriggerProvider accessToken={searchParams.publicAccessToken}>
|
|
<RunDetails id={params.id} />
|
|
</TriggerProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
Another alternative would be to use a server-side rendered page to fetch the token and pass it to the frontend:
|
|
|
|
<CodeGroup>
|
|
|
|
```tsx pages/runs/[id].tsx
|
|
import { TriggerProvider } from "@/components/TriggerProvider";
|
|
import { generatePublicAccessToken } from "@/trigger/auth";
|
|
|
|
export default async function RunPage({ params }: { params: { id: string } }) {
|
|
// This will be executed on the server only
|
|
const publicAccessToken = await generatePublicAccessToken(params.id);
|
|
|
|
return (
|
|
<TriggerProvider accessToken={publicAccessToken}>
|
|
<RunDetails id={params.id} />
|
|
</TriggerProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
```tsx trigger/auth.ts
|
|
import { auth } from "@trigger.dev/sdk/v3";
|
|
|
|
export async function generatePublicAccessToken(runId: string) {
|
|
return auth.createPublicToken({
|
|
scopes: {
|
|
read: {
|
|
runs: [runId],
|
|
},
|
|
},
|
|
expirationTime: "1h",
|
|
});
|
|
}
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
## SWR vs Realtime hooks
|
|
|
|
We offer two "styles" of hooks: SWR and Realtime. The SWR hooks use the [swr](https://swr.vercel.app/) library to fetch data once and cache it. The Realtime hooks use [Trigger.dev realtime](/realtime) to subscribe to updates in real-time.
|
|
|
|
<Note>
|
|
It can be a little confusing which one to use because [swr](https://swr.vercel.app/) can also be
|
|
configured to poll for updates. But because of rate-limits and the way the Trigger.dev API works,
|
|
we recommend using the Realtime hooks for most use-cases.
|
|
</Note>
|
|
|
|
All hooks named `useRealtime*` are Realtime hooks, and all hooks named `use*` are SWR hooks.
|
|
|
|
## Realtime 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>;
|
|
}
|
|
```
|
|
|
|
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>
|
|
);
|
|
}
|
|
```
|
|
|
|
See our [Realtime documentation](/realtime) for more information.
|
|
|
|
### 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
|
|
|
|
#### 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>
|
|
);
|
|
}
|
|
```
|
|
|
|
## SWR Hooks
|
|
|
|
### useRun
|
|
|
|
The `useRun` hook allows you to fetch a run by its ID.
|
|
|
|
```tsx
|
|
"use client"; // This is needed for Next.js App Router or other RSC frameworks
|
|
|
|
import { useRun } from "@trigger.dev/react-hooks";
|
|
|
|
export function MyComponent({ runId }: { runId: string }) {
|
|
const { run, error, isLoading } = useRun(runId);
|
|
|
|
if (isLoading) return <div>Loading...</div>;
|
|
if (error) return <div>Error: {error.message}</div>;
|
|
|
|
return <div>Run: {run.id}</div>;
|
|
}
|
|
```
|
|
|
|
The `run` object returned is the same as the [run object](/management/runs/retrieve) returned by the Trigger.dev API. To correctly type the run's payload and output, you can provide the type of your task to the `useRun` hook:
|
|
|
|
```tsx
|
|
import { useRun } from "@trigger.dev/react-hooks";
|
|
import type { myTask } from "@/trigger/myTask";
|
|
|
|
export function MyComponent({ runId }: { runId: string }) {
|
|
const { run, error, isLoading } = useRun<typeof myTask>(runId, {
|
|
refreshInterval: 0, // Disable polling
|
|
});
|
|
|
|
if (isLoading) return <div>Loading...</div>;
|
|
if (error) return <div>Error: {error.message}</div>;
|
|
|
|
// Now run.payload and run.output are correctly typed
|
|
|
|
return <div>Run: {run.id}</div>;
|
|
}
|
|
```
|
|
|
|
### Common options
|
|
|
|
You can pass the following options to the all SWR hooks:
|
|
|
|
<ParamField path="revalidateOnFocus" type="boolean">
|
|
Revalidate the data when the window regains focus.
|
|
</ParamField>
|
|
|
|
<ParamField path="revalidateOnReconnect" type="boolean">
|
|
Revalidate the data when the browser regains a network connection.
|
|
</ParamField>
|
|
|
|
<ParamField path="refreshInterval" type="number">
|
|
Poll for updates at the specified interval (in milliseconds). Polling is not recommended for most
|
|
use-cases. Use the Realtime hooks instead.
|
|
</ParamField>
|
|
|
|
### Common return values
|
|
|
|
<ResponseField name="error" type="Error">
|
|
An error object if an error occurred while fetching the data.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="isLoading" type="boolean">
|
|
A boolean indicating if the data is currently being fetched.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="isValidating" type="boolean">
|
|
A boolean indicating if the data is currently being revalidated.
|
|
</ResponseField>
|
|
|
|
<ResponseField name="isError" type="boolean">
|
|
A boolean indicating if an error occurred while fetching the data.
|
|
</ResponseField>
|
|
|
|
## Trigger Hooks
|
|
|
|
We provide a set of hooks that can be used to trigger tasks from your frontend application. You'll need to generate a Public Access Token with `write` permissions to use these hooks. See our [frontend guide](/frontend/overview#write-scopes) for more information.
|
|
|
|
### useTaskTrigger
|
|
|
|
The `useTaskTrigger` hook allows you to trigger a task from your frontend application.
|
|
|
|
```tsx
|
|
"use client"; // This is needed for Next.js App Router or other RSC frameworks
|
|
|
|
import { useTaskTrigger } from "@trigger.dev/react-hooks";
|
|
import type { myTask } from "@/trigger/myTask";
|
|
|
|
export function MyComponent({ publicAccessToken }: { publicAccessToken: string }) {
|
|
const { submit, handle, error, isLoading } = useTaskTrigger<typeof myTask>("my-task", {
|
|
accessToken: publicAccessToken,
|
|
});
|
|
|
|
if (error) {
|
|
return <div>Error: {error.message}</div>;
|
|
}
|
|
|
|
if (handle) {
|
|
return <div>Run ID: {handle.id}</div>;
|
|
}
|
|
|
|
return (
|
|
<button onClick={() => submit({ foo: "bar" })} disabled={isLoading}>
|
|
{isLoading ? "Loading..." : "Trigger Task"}
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
### useRealtimeTaskTrigger
|
|
|
|
The `useRealtimeTaskTrigger` hook allows you to trigger a task from your frontend application and then subscribe to the run in using Realtime:
|
|
|
|
```tsx
|
|
"use client"; // This is needed for Next.js App Router or other RSC frameworks
|
|
|
|
import { useRealtimeTaskTrigger } from "@trigger.dev/react-hooks";
|
|
import type { myTask } from "@/trigger/myTask";
|
|
|
|
export function MyComponent({ publicAccessToken }: { publicAccessToken: string }) {
|
|
const { submit, run, error, isLoading } = useRealtimeTaskTrigger<typeof myTask>("my-task", {
|
|
accessToken: publicAccessToken,
|
|
});
|
|
|
|
if (error) {
|
|
return <div>Error: {error.message}</div>;
|
|
}
|
|
|
|
// This is the realtime run object, which will automatically update when the run changes
|
|
if (run) {
|
|
return <div>Run ID: {run.id}</div>;
|
|
}
|
|
|
|
return (
|
|
<button onClick={() => submit({ foo: "bar" })} disabled={isLoading}>
|
|
{isLoading ? "Loading..." : "Trigger Task"}
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
### useRealtimeTaskTriggerWithStreams
|
|
|
|
The `useRealtimeTaskTriggerWithStreams` hook allows you to trigger a task from your frontend application and then subscribe to the run in using Realtime, and also receive any streams that are emitted by the task.
|
|
|
|
```tsx
|
|
"use client"; // This is needed for Next.js App Router or other RSC frameworks
|
|
|
|
import { useRealtimeTaskTriggerWithStreams } 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({ publicAccessToken }: { publicAccessToken: string }) {
|
|
const { submit, run, streams, error, isLoading } = useRealtimeTaskTriggerWithStreams<
|
|
typeof myTask,
|
|
STREAMS
|
|
>("my-task", {
|
|
accessToken: publicAccessToken,
|
|
});
|
|
|
|
if (error) {
|
|
return <div>Error: {error.message}</div>;
|
|
}
|
|
|
|
if (streams && run) {
|
|
const text = streams.openai?.map((part) => part).join("");
|
|
|
|
return (
|
|
<div>
|
|
<div>Run ID: {run.id}</div>
|
|
<div>{text}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button onClick={() => submit({ foo: "bar" })} disabled={isLoading}>
|
|
{isLoading ? "Loading..." : "Trigger Task"}
|
|
</button>
|
|
);
|
|
}
|
|
```
|