We provide a set of hooks that can be used to trigger tasks from your frontend application.

Demo

We’ve created a Demo application that demonstrates how to use our React hooks to trigger tasks in a Next.js application. The application uses the @trigger.dev/react-hooks package to trigger a task and subscribe to the run in real-time.

Installation

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

Authentication

To authenticate a trigger hook, you must provide a special one-time use “trigger” token. These tokens are very similar to Public Access Tokens, but they can only be used once to trigger a task. You can generate a trigger token using the auth.createTriggerPublicToken function in your backend code:

import { auth } from "@trigger.dev/sdk/v3";
// Somewhere in your backend code
const triggerToken = await auth.createTriggerPublicToken("my-task");

These tokens also expire, with the default expiration time being 15 minutes. You can specify a custom expiration time by passing a expirationTime parameter:

import { auth } from "@trigger.dev/sdk/v3";
// Somewhere in your backend code
const triggerToken = await auth.createTriggerPublicToken("my-task", {
  expirationTime: "24hr",
});

You can also pass multiple tasks to the createTriggerPublicToken function to create a token that can trigger multiple tasks:

import { auth } from "@trigger.dev/sdk/v3";
// Somewhere in your backend code
const triggerToken = await auth.createTriggerPublicToken(["my-task-1", "my-task-2"]);

You can also pass the multipleUse parameter to create a token that can be used multiple times:

import { auth } from "@trigger.dev/sdk/v3";

// Somewhere in your backend code
const triggerToken = await auth.createTriggerPublicToken("my-task", {
  multipleUse: true, // ❌ Use this with caution!
});

After generating the trigger token in your backend, you must pass it to your frontend application. We have a guide on how to do this in the React hooks overview.

Hooks

useTaskTrigger

The useTaskTrigger hook allows you to trigger a task from your frontend application.

"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";
//     👆 This is the type of your task

export function MyComponent({ publicAccessToken }: { publicAccessToken: string }) {
  //                         pass the type of your task here 👇
  const { submit, handle, error, isLoading } = useTaskTrigger<typeof myTask>("my-task", {
    accessToken: publicAccessToken, // 👈 this is the "trigger" token
  });

  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>
  );
}

useTaskTrigger returns an object with the following properties:

  • submit: A function that triggers the task. It takes the payload of the task as an argument.
  • handle: The run handle object. This object contains the ID of the run that was triggered, along with a Public Access Token that can be used to access the run.
  • isLoading: A boolean that indicates whether the task is currently being triggered.
  • error: An error object that contains any errors that occurred while triggering the task.

The submit function triggers the task with the specified payload. You can additionally pass an optional options argument to the submit function:

submit({ foo: "bar" }, { tags: ["tag1", "tag2"] });

Using the handle object

You can use the handle object to initiate a subsequent realtime hook to subscribe to the run.

"use client"; // This is needed for Next.js App Router or other RSC frameworks

import { useTaskTrigger, useRealtimeRun } from "@trigger.dev/react-hooks";
import type { myTask } from "@/trigger/myTask";
//     👆 This is the type of your task

export function MyComponent({ publicAccessToken }: { publicAccessToken: string }) {
  //                         pass the type of your task here 👇
  const { submit, handle, error, isLoading } = useTaskTrigger<typeof myTask>("my-task", {
    accessToken: publicAccessToken, // 👈 this is the "trigger" token
  });

  //     use the handle object to preserve type-safety 👇
  const { run, error: realtimeError } = useRealtimeRun(handle, {
    accessToken: handle?.publicAccessToken,
    enabled: !!handle, // Only subscribe to the run if the handle is available
  });

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  if (handle) {
    return <div>Run ID: {handle.id}</div>;
  }

  if (realtimeError) {
    return <div>Error: {realtimeError.message}</div>;
  }

  if (run) {
    return <div>Run ID: {run.id}</div>;
  }

  return (
    <button onClick={() => submit({ foo: "bar" })} disabled={isLoading}>
      {isLoading ? "Loading..." : "Trigger Task"}
    </button>
  );
}

We’ve also created some additional hooks that allow you to trigger tasks and subscribe to the run in one step:

useRealtimeTaskTrigger

The useRealtimeTaskTrigger hook allows you to trigger a task from your frontend application and then subscribe to the run in using Realtime:

"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.

"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>
  );
}