# React hooks / Next.js <VersionBadge version=

import {
  RiNextjsFill,
  RiNodejsFill,
} from "@remixicon/react";

TypeScript SDK v3.32.0+" />

Realtime provides a [`useInngestSubscription()`](#use-inngest-subscription-api-reference) React hook, offering a fully typed experience for subscribing to channels.

`useInngestSubscription()` securely subscribes to channels using a subscription token fetched from the server.

In Next.js, this is implemented as a server action that returns a token, which is then used by the client to subscribe:

```tsx {{filename: "src/actions.ts"}}
"use server";
// securely fetch an Inngest Realtime subscription token from the server as a server action
export async function fetchSubscriptionToken(): Promise<Realtime.Token<typeof helloChannel, ["logs"]>> {
  await getSubscriptionToken(getInngestApp(), {
    channel: helloChannel(),
    topics: ["logs"],
  });

  return token;
}
```

```tsx {{filename: "src/App.tsx"}}
"use client";

// import the server action to securely fetch the Realtime subscription token
export default function Home() {
  // subscribe to the hello-world channel via the subscription token
  // `data` is fully typed based on the selected channel and topics!
  useInngestSubscription({
    refreshToken: fetchRealtimeSubscriptionToken,
  });

  return (
    <div>
      <h1>Realtime</h1>
      {data.map((message, i) => (
        <div key={i}>{message.data}</div>
      ))}
    </div>
  )
}
```

#

### Parameters

- `enabled?: boolean` - Whether or not the hook will subscribe.
- `bufferInterval?: number` - If set and above `0`, the outputs will only update every `n` milliseconds. This helps with very busy streams that could overwhelm a UI.
- `token?: Realtime.Subscribe.Token` - The token to be used for subscribing (see [Subscribe from the client](/docs/features/realtime#subscribe-from-the-client)).
- `refreshToken?: () => Promise<Realtime.Subscribe.Token>` - A function that will be called if no `token` is available, or if the hook has been re-`enabled` and the previous `token` has expired.

<Warning>
  A `token` or `refreshToken` parameter is required.
</Warning>

### Return value

- `data: Array<Realtime.Message>` - All messages received on the subscription in chronological order.
- `latestData: Realtime.Message` - A shortcut to the last message received on the subscription. Useful for streams where each message is the latest state of an entity.
- `freshData: Array<Realtime.Message>` - If `bufferInterval` is active, this will be the last batch of messages released from the buffer. If `bufferInterval` is inactive, this is always the latest message.
- `error: Error | null` - If truthy, this indicates an error with the subscription.
- `state: InngestSubscriptionState` - The current state of the subscription, one of `"closed"`, `"error"`, `"refresh_token"`, `"connecting"`, `"active"`, or `"closing"`.
- `clear: () => void` - A function to clear all accumulated message data from the internal state. This includes `data`, `freshData`, and `latestData` arrays. Does not affect the connection or error state.

## Examples

<CardGroup cols={2}>

  <Card
    href="https://github.com/inngest/inngest-js/tree/main/examples/realtime/next-realtime-hooks"
    title={"useInngestSubscription() Next.js demo"}
    icon={<RiNextjsFill className="text-basis h-8 w-8"/>}
    iconPlacement="top"
  >
   Clone this demo to see an interactive example of the `useInngestSubscription()` hook in action.
  </Card>

  <Card
    href="/docs/examples/realtime"
    title={"Explore patterns and examples"}
    icon={<RiNodejsFill className="text-basis h-8 w-8"/>}
    iconPlacement="top"
  >
   Use Realtime to stream updates from one or multiple Inngest functions, or to implement a Human-in-the-Loop mechanism.
  </Card>

</CardGroup>