> ## Documentation Index
> Fetch the complete documentation index at: https://trigger-triggering-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> 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, and subscribe to real-time updates, and trigger tasks from your frontend application.

## Installation

Install the `@trigger.dev/react-hooks` package in your project:

<CodeGroup>
  ```bash npm theme={null}
  npm add @trigger.dev/react-hooks
  ```

  ```bash pnpm theme={null}
  pnpm add @trigger.dev/react-hooks
  ```

  ```bash yarn theme={null}
  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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
"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 theme={null}
"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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
  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 theme={null}
  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>

## SWR Hooks

### useRun

The `useRun` hook allows you to fetch a run by its ID.

```tsx theme={null}
"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 theme={null}
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>

## Realtime hooks

See our [Realtime hooks documentation](/frontend/react-hooks/realtime) for more information.

## Trigger Hooks

See our [Trigger hooks documentation](/frontend/react-hooks/triggering) for more information.
