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. You can use these hooks to fetch runs, batches, and subscribe to real-time updates.
Before you can use the hooks, you need to provide a public access token to the TriggerAuthContext provider. Learn more about authentication in the frontend guide.
Copy
Ask AI
import { TriggerAuthContext } from "@trigger.dev/react-hooks";export function SetupTrigger() { return ( <TriggerAuthContext.Provider value={{ accessToken: "your-access-token" }}> <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.
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:
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:
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.
actions/trigger.ts
Copy
Ask AI
"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); 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.
Another alternative would be to use a server-side rendered page to fetch the token and pass it to the frontend:
Copy
Ask AI
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> );}
We offer two “styles” of hooks: SWR and Realtime. The SWR hooks use the swr library to fetch data once and cache it. The Realtime hooks use Trigger.dev realtime to subscribe to updates in real-time.
It can be a little confusing which one to use because swr 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.
All hooks named useRealtime* are Realtime hooks, and all hooks named use* are SWR hooks.
The useRun hook allows you to fetch a run by its ID.
Copy
Ask AI
"use client"; // This is needed for Next.js App Router or other RSC frameworksimport { 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 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:
Copy
Ask AI
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); 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>;}
The useRealtimeRunsWithTag hook allows you to subscribe to multiple runs with a specific tag.
Copy
Ask AI
"use client"; // This is needed for Next.js App Router or other RSC frameworksimport { 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:
Copy
Ask AI
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:
Copy
Ask AI
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> );}