This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13) .

Notifications

The Stream Chat client can create notifications that are then rendered through NotificationList.

client.notifications.add({ message, origin, options });
client.notifications.addError({ message, origin, options });
client.notifications.addWarning({ message, origin, options });
client.notifications.addInfo({ message, origin, options });
client.notifications.addSuccess({ message, origin, options });

NotificationList renders client notifications from client.notifications.

Inside MessageList and VirtualizedMessageList, the default notification stack is split like this:

  • MessageListNotifications renders channel notifications from ChannelStateContext.notifications plus connection status UI
  • NotificationList renders client notifications scoped to the message-list panel

Best Practices

  • Use severity levels to keep notifications meaningful.
  • Keep notification copy concise and actionable.
  • Prefer NotificationList for client-notification customization and filtering.
  • Use MessageListNotifications only when you need to change the channel-notification container or ConnectionStatus layout.
  • Translate notifications through the notification topic for consistency.
  • Avoid over-notifying noisy or repeating events.

To build and translate notification text, register translator functions for the notification topic. See the notification translation guide.

Customizing NotificationList

Use WithComponents to replace the default client-notification surface:

import {
  Channel,
  ChannelHeader,
  MessageInput,
  MessageList,
  NotificationList,
  Thread,
  Window,
  WithComponents,
  type NotificationListProps,
} from "stream-chat-react";

const CustomNotificationList = (props: NotificationListProps) => (
  <div className="custom-notification-list">
    <NotificationList {...props} verticalAlignment="top" />
  </div>
);

const App = () => (
  <WithComponents overrides={{ NotificationList: CustomNotificationList }}>
    <Channel>
      <Window>
        <ChannelHeader />
        <MessageList />
        <MessageInput />
      </Window>
      <Thread />
    </Channel>
  </WithComponents>
);

Use panel, fallbackPanel, or filter on NotificationList when you need panel-specific routing or client-notification filtering.

If you need to customize channel notifications and connection status inside the message list specifically, override MessageListNotifications instead. MessageListNotifications only controls that channel-notification container. The unread UI and new-message UI are handled separately by UnreadMessagesNotification, NewMessageNotification, and ScrollToLatestMessageButton.

The sections below cover notification management in NotificationManager.

NotificationManager

NotificationManager centralizes notification creation and display across severities (error, warning, info, success) with configurable duration and behavior.

Accessing NotificationManager

NotificationManager is available on the StreamChat client:

const client = new StreamChat(apiKey, token);
const notificationManager = client.notifications;

Notification Severity Types

The manager supports four severity levels:

type NotificationSeverity = "error" | "warning" | "info" | "success";

Each severity defaults to 3000ms (3 seconds).

Adding Notifications

Basic Usage

// Add a notification with default severity (info)
const id = client.notifications.add({
  message: "Operation completed",
  origin: {
    emitter: "MyComponent",
    context: {
      /* any relevant context */
    },
  },
});

Specific Severity Methods

// Add error notification
client.notifications.addError({
  message: "Operation failed",
  origin: { emitter: "MyComponent" },
});

// Add warning notification
client.notifications.addWarning({
  message: "Operation might fail",
  origin: { emitter: "MyComponent" },
});

// Add info notification
client.notifications.addInfo({
  message: "Operation in progress",
  origin: { emitter: "MyComponent" },
});

// Add success notification
client.notifications.addSuccess({
  message: "Operation succeeded",
  origin: { emitter: "MyComponent" },
});

Advanced Options

client.notifications.add({
  message: "Custom notification",
  origin: { emitter: "MyComponent" },
  options: {
    severity: "warning",
    duration: 8000, // Override default duration
    actions: [
      {
        label: "Retry",
        handler: () => {
          /* handle retry */
        },
      },
    ],
    metadata: {
      /* custom data */
    },
  },
});

Managing Notifications

Removing Notifications

// Remove specific notification
client.notifications.remove(notificationId);

// Clear all notifications
client.notifications.clear();

Accessing Current Notifications

// Get all notifications
const allNotifications = client.notifications.notifications;

// Get notifications by severity
const errors = client.notifications.error;
const warnings = client.notifications.warning;
const infos = client.notifications.info;
const successes = client.notifications.success;

Subscribing to State Changes

NotificationManager uses a StateStore. Subscribe to state changes:

// Subscribe to all notification changes
const unsubscribe = client.notifications.store.subscribe(
  (nextValue, previousValue) => {
    // Handle notification state changes
    console.log("New notifications:", nextValue.notifications);
    console.log("Previous notifications:", previousValue?.notifications);
  },
);

// Clean up subscription
unsubscribe();

State Structure

The NotificationManager state has the following structure:

type NotificationState = {
  notifications: Array<{
    id: string;
    message: string;
    origin: {
      emitter: string;
      context?: Record<string, unknown>;
    };
    severity: NotificationSeverity;
    createdAt: number;
    actions?: Array<{
      label: string;
      handler: () => void;
      metadata?: Record<string, unknown>;
    }>;
    expiresAt?: number;
    metadata?: Record<string, unknown>;
    originalError?: Error;
    type?: string;
  }>;
};

Notification Types

You can group notifications by assigning type. The SDK uses a unified format:

domain:entity:operation:result
  • domain: where it occurred (api, validation, permission)
  • entity: what it affected (poll, attachment, message)
  • operation: what was attempted (create, upload, validate)
  • result: outcome (failed, blocked, invalid)

Examples:

  • validation:attachment:file:missing
  • validation:attachment:upload:blocked
  • api:attachment:upload:failed
  • api:poll:create:failed

Example error notification emitted by AttachmentManager:

client.notifications.addError({
  message: `The attachment upload was blocked`,
  origin: {
    emitter: "AttachmentManager",
    context: { attachment, blockedAttachment: localAttachment },
  },
  options: {
    type: "validation:attachment:upload:blocked",
    metadata: {
      reason: localAttachment.localMetadata.uploadPermissionCheck?.reason,
    },
  },
});

Best Practices

  1. Origin Tracking
  • Provide a clear origin.emitter
  • Include minimal context needed for debugging
  1. Duration Management
  • Match duration to severity and UX needs
  1. State Cleanup
  • Remove notifications that no longer apply
  • Clear notifications when the UI context changes
  1. Error Handling
  • Use error notifications for real failures
  • Make messages actionable
  1. Performance
  • Unsubscribe on unmount
  • Avoid spamming notifications