# Notification hooks

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

These hooks read the notifications in `client.notifications` and publish new ones from a component. They're exported from `stream-chat-react`.

What a notification holds, and who publishes which, is on [Publishing notifications](https://getstream.io/chat/docs/sdk/react/v15/state/publishing-notifications/). How `NotificationList` shows them, and how a notification reaches a panel, is on [Displaying notifications](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/displaying-notifications/).

Each entry gives the signature, then:

- **Returns:** what the hook gives back.
- **Reads:** the store or the context it reads.
- **Re-renders:** what makes the component render again.
- **Needs:** where the component must sit, and what the hook does outside that place.

## useNotifications

Returns the notifications in `client.notifications`, narrowed by the options.

```ts
useNotifications(options?: UseNotificationsOptions): Notification[]
```

The options, each optional:

- `panel`: keep only the notifications routed to this panel, `'channel'`, `'thread'`, `'channel-list'`, `'thread-list'` or `'modal'`. [Routing notifications](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/displaying-notifications/#routing-notifications) explains the routing.
- `fallbackPanel`: the panel a notification without a panel tag belongs to. `'channel'` by default.
- `applyDisplayFilter`: also apply the [display filter](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/displaying-notifications/#display-filter) of `Chat` or of the nearest `NotificationConfigurationProvider`, as `NotificationList` does.
- `filter`: `(notification) => boolean`, applied last.

- **Returns:** the notifications that pass, in the order of the store. Without options, every notification, system notifications included. System notifications carry no panel tag, so they also pass for the `fallbackPanel`, `'channel'` unless you set it: drop them with `hasSystemNotificationTag`.
- **Reads:** `client.notifications.store`, field `notifications`.
- **Re-renders:** whenever a notification is added or removed, even one the options drop. A new `filter` function subscribes again, so define it at module scope, as in [Selector identity](https://getstream.io/chat/docs/sdk/react/v15/ui/reading-state-in-components/#selector-identity).
- **Needs:** `Chat`. Throws outside it.

A notification you render this way leaves only when its countdown runs. Start it with `ensureNotificationTimeout(id)` from [`useNotificationApi`](#usenotificationapi) once it's on screen:

```tsx
import { useEffect } from "react";
import type { Notification } from "stream-chat";
import {
  hasSystemNotificationTag,
  useNotificationApi,
  useNotifications,
} from "stream-chat-react";

const isPanelNotification = (notification: Notification) =>
  !hasSystemNotificationTag(notification);

export const ChannelToasts = () => {
  const notifications = useNotifications({
    filter: isPanelNotification,
    panel: "channel",
  });
  const { ensureNotificationTimeout, removeNotification } =
    useNotificationApi();

  useEffect(() => {
    notifications.forEach(({ id }) => ensureNotificationTimeout(id));
  }, [ensureNotificationTimeout, notifications]);

  return (
    <ul className="toasts">
      {notifications.map(({ id, message }) => (
        <li key={id}>
          {message}
          <button onClick={() => removeNotification(id)} type="button">
            Close
          </button>
        </li>
      ))}
    </ul>
  );
};
```

## useSystemNotifications

Returns the system notifications: the ones about the whole app, such as "Reconnecting…".

```ts
useSystemNotifications(options?: UseSystemNotificationsOptions): Notification[]
```

- **Returns:** the notifications tagged `system`, narrowed by `options.filter` when you pass one. `Chat` publishes the lost-connection notification this way, and no `NotificationList` shows it.
- **Reads:** `client.notifications.store`, field `notifications`.
- **Re-renders:** whenever a notification is added or removed. Define `filter` at module scope, as for `useNotifications`.
- **Needs:** `Chat`. Throws outside it.

[System notifications](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/displaying-notifications/#system-notifications) renders a connection banner with it, and the [System notification banner](https://getstream.io/chat/docs/sdk/react/v15/recipes/app/system-notification-banner/) recipe builds a complete one.

## useNotificationApi

Returns the functions a component publishes and removes notifications with.

```ts
useNotificationApi(): NotificationApi
```

- **Returns:**
  - `addNotification(params)`: publishes a notification tagged for the panel the component sits in, the one [`useNotificationTarget`](#usenotificationtarget) returns. While a modal is open, it also tags it for the `modal` panel. Returns nothing.
  - `addSystemNotification(params)`: publishes a notification tagged `system` and for no panel. Returns its id.
  - `removeNotification(id)`: removes a notification.
  - `startNotificationTimeout(id)`: starts a notification's countdown, from the beginning if it's already running.
  - `ensureNotificationTimeout(id)`: starts the countdown unless it's already running.
- **Reads:** the panel from `useNotificationTarget()`, and whether a modal is open from the modal dialog manager.
- **Re-renders:** when the component's panel changes, and when a modal opens or closes.
- **Needs:** `Chat`. Throws outside it.

`addNotification` takes:

| Param          | What it does                                                                                                                                                                        |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `message`      | the text to show. Required.                                                                                                                                                         |
| `emitter`      | who published it, such as the component's name. Required.                                                                                                                           |
| `severity`     | `'error'`, `'warning'`, `'info'`, `'success'`, or a string of your own such as `'loading'`. The first four have a default duration.                                                 |
| `type`         | what the notification is about, such as `'api:message:pin:success'`. Translators and filters match on it.                                                                           |
| `incident`     | `{ domain, entity, operation, status? }`, used to build `type` when you don't pass one. `status` defaults to `failed` for an `error`, `success` for a `success`, else the severity. |
| `duration`     | milliseconds before it leaves, counted from when it's shown.                                                                                                                        |
| `actions`      | buttons, each `{ label, handler }`.                                                                                                                                                 |
| `context`      | data stored as `origin.context`, such as the message it's about.                                                                                                                    |
| `error`        | the error that caused it, stored as `originalError`.                                                                                                                                |
| `tags`         | tags added next to the panel tags.                                                                                                                                                  |
| `targetPanels` | the panels to show it in, instead of the component's own.                                                                                                                           |
| `ariaLive`     | `'polite'` or `'assertive'`: how urgently screen readers announce it. By default `assertive` for an `error`, `polite` otherwise.                                                    |

`addSystemNotification` takes the same, without `targetPanels`.

```tsx
import { useNotificationApi } from "stream-chat-react";

const exportIncident = { domain: "api", entity: "chat", operation: "export" };

export const ExportButton = ({
  exportChat,
}: {
  exportChat: () => Promise<void>;
}) => {
  const { addNotification } = useNotificationApi();

  const onClick = async () => {
    try {
      await exportChat();
      // Published as api:chat:export:success
      addNotification({
        emitter: "ExportButton",
        incident: exportIncident,
        message: "Chat exported",
        severity: "success",
      });
    } catch (error) {
      // Published as api:chat:export:failed
      addNotification({
        emitter: "ExportButton",
        error: error instanceof Error ? error : undefined,
        incident: exportIncident,
        message: "The chat could not be exported",
        severity: "error",
      });
    }
  };

  return (
    <button onClick={onClick} type="button">
      Export
    </button>
  );
};
```

Outside `Chat`, or from code that isn't a component, publish with `client.notifications` directly, as [Publishing a notification](https://getstream.io/chat/docs/sdk/react/v15/state/publishing-notifications/#publishing-a-notification) shows. Those notifications carry no panel tag.

## useNotificationTarget

Returns the panel the component sits in.

```ts
useNotificationTarget(): NotificationTargetPanel | undefined
```

- **Returns**, the first that applies:
  1. `'thread'` inside a `Thread`;
  2. `'channel'` inside a `Channel`;
  3. `'thread-list'` while the layout shows the threads view;
  4. `'channel-list'` inside `ChannelLists`;
  5. `undefined`.
- **Reads:** the `Thread`, `Channel`, workspace navigation and channel list contexts. No store.
- **Re-renders:** when one of those contexts changes.
- **Needs:** nothing. Never throws.

`MessageList` uses it to pick the panel of its notification list. A list of your own can do the same:

```tsx
import { NotificationList, useNotificationTarget } from "stream-chat-react";

export const PanelNotifications = () => {
  const panel = useNotificationTarget();
  return <NotificationList panel={panel ?? "channel"} />;
};
```

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/notification-hooks/](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/notification-hooks/).