Skip to main content
Version: 1.x.x

PubSub - React

PubSub is a concise acronym for the Publish-Subscribe mechanism. This mechanism is employed to send and receive messages within a specified topic. As the name implies, to send a message, one must specify the topic and the message to be published. Similarly, to receive a message, a subscriber must be connected to that particular topic.

Here is a visual to better understand the publish-subscribe mechanism.

pubsub

usePubSub

To utilize PubSub in a meeting, VideoSDK provides a hook called usePubSub. This hook enables you to subscribe to any topic and publish to any topic, facilitating the exchange of messages and instructions seamlessly during the meeting.

The hook automatically subscribes to the topic on mount and unsubscribes on unmount — you never call subscribe / unsubscribe yourself.

publish()

  • This method is used for publishing a message for a specific topic.
  • It can be accessed from the usePubSub hook by specifying the topic for which publish() will be used.
  • It will accept following parameters as input:
    • message: This parameter represents the actual message to be published and should be in String format.
    • options: This object specifies the options for publishing. You can set following properties :
      • persist : When set to true, this option retains the message for the duration of the session. If persist is true, the message will be available for upcoming participants and can be accessed in the VideoSDK Session Dashboard in CSV format after the session is completed.
      • sendOnly: If you want to send a message to specific participants, you can pass their respective participantId here. If you don't provide any IDs, the message will be sent to all participants by default.
    • payload: If you need to include additional information along with a message, you can pass it here as an object.
// importing usePubSub hook from react-sdk
import { usePubSub } from "@videosdk.live/react-sdk";

function MeetingView() {
// destructure publish method from usePubSub hook
const { publish } = usePubSub("CHAT");

const handlePublishMessage = () => {
// publish message
const message = "Hello Everyone!";
try {
await publish(message, { persist: true });
} catch (e) {
console.log("Error while sending message through pubsub", e);
}
};

return (
<>
<button onClick={handlePublishMessage}>Publish Message</button>
</>
);
}

usePubSub() callbacks and options

  • usePubSub(topic, listeners?, properties?) returns { publish, messages, topic }. The second argument is a listeners object (onMessageReceived, onBatchReceived, onOldMessagesReceived, onMessageDrop). The third argument is a properties object (maxMessages, bufferMessages, oldMessageLimit, realtimeOverflow, maxQueue, newMessageLimit).
  • It will accept following parameters as input:
    • topic: The topic to subscribe to and publish on.
    • listeners: An object containing listener callbacks:
      • onMessageReceived(message) — Called for every realtime message as soon as it is received.

        • Use this when: You want to handle each message individually — trigger a notification, play a sound, or update message-specific state.
        • Don't use this when: The topic is high-throughput (busy chats, live reactions, cursor positions). Firing once per message causes excessive re-renders — use onBatchReceived instead, or pair with bufferMessages: false and throttle inside the callback.
      • onBatchReceived(messages) — Called with an array of realtime messages; the same set surfaced one-by-one through onMessageReceived, grouped for bulk handling.

        • Use this when: A single state update per batch is cheaper than one per message (large chat lists, virtualized rendering).
      • onOldMessagesReceived(messages, { isLast }) — Called with persisted history in batches — fires once per batch until history is fully delivered. Only messages published with persist: true are delivered here. isLast is true on the final batch.

        • Use this when: Loading chat history or restoring previously sent messages when a participant joins the meeting.
      • onMessageDrop(info) — Called when incoming realtime messages cannot be delivered. This can happen:

        • because the client cannot keep up with the incoming message rate (for example, due to a slow network or high CPU usage), causing overflow, or
        • because newMessageLimit is configured, which intentionally limits how many realtime messages are delivered every 500 ms. Any messages exceeding the configured limit within that window are discarded.

        info.droppedCount contains the number of messages that were not delivered.

        • Use this when: Notifying users that some realtime messages were missed, monitoring the effects of newMessageLimit, or logging dropped messages for debugging and observability.
    • properties: This object specifies the hook properties. You can set following properties:
      • maxMessages (number | null) — Hard cap on the number of messages retained in the returned messages array. Once the cap is reached, the oldest messages are dropped to make room for new ones. Pass null to retain every message. Default: null.
        • When to use: Cap history on high-frequency topics to prevent unbounded memory growth. For example, keep only the last 100 messages in a busy chat.
      • bufferMessages (boolean) — Controls whether incoming messages accumulate in the returned messages array. When true (default), messages are stored in messages and delivered to the callbacks. When false, messages are delivered only via the callbacks and the messages array is never populated. Default: true.
        • When to use: Set to false on high-throughput topics (thousands of messages per second) where retaining a re-rendering array is undesirable — handle messages manually inside onMessageReceived / onBatchReceived instead.
      • oldMessageLimit (number) — How many old messages to receive. Pass 0 to receive none. If omitted, all old messages are delivered. Default: all.
        • When to use: Cap history for large sessions where loading every persisted message would be wasteful (e.g. only the last 50 messages need to appear when a participant joins).
      • realtimeOverflow ("queue" | "drop" / Constants.RealtimeOverflow) — Behavior when the client can't keep up. "queue" (default) queues remaining messages so you receive them once you catch up; "drop" drops them instead.
        • When to use: Use "queue" for chat where every message matters. Use "drop" for high-frequency, low-value streams (live reactions, cursor positions) where stale data is worse than missing data.
      • maxQueue (number) — Maximum number of message batches to queue during overflow. Default: 70. Max: 200. Only valid with realtimeOverflow: "queue".
        • When to use: Increase this value when you want to retain more messages and catch up after recovering from a slow network or CPU spike. Lower it if memory pressure matters more than history.
      • newMessageLimit (number) — Maximum number of realtime messages to receive per 500 ms.
        • When to use: Set this when you want to throttle a busy topic so the UI doesn't jank, or rate-limit a reactions topic.
note

If usePubSub() is called again on the same topic with different values (for example, another usePubSub instance mounts for the same topic with a different listeners object or different properties), the values of realtimeOverflow, maxQueue, and newMessageLimit are overridden by the latest usePubSub() call. Other properties (such as oldMessageLimit) are not affected.

Every message in the messages array and every message delivered to the callbacks contains the following fields:

  • id — unique identifier for the message.
  • message — the actual message content that was sent.
  • senderIdparticipantId of the participant who sent the message.
  • senderNamedisplayName of the participant who sent the message.
  • timestamp — the timestamp indicating when the message was published.
  • topic — the topic the message was published to.
  • payload — any additional data sent along with the message (optional).
// importing usePubSub hook and Constants from react-sdk
import { usePubSub, Constants } from "@videosdk.live/react-sdk";

function ChatView() {
const listeners = {
onMessageReceived: (message) => {
console.log("New Message Received", message);
},
onBatchReceived: (messages) => {
// Handle a batch of realtime messages together
console.log(`Batch received with ${messages.length} messages`);
},
onOldMessagesReceived: (messages, { isLast }) => {
console.log("Old Messages published with persist:true Received", messages, isLast);
},
onMessageDrop: (info) => {
// Called when incoming messages are dropped
console.log(`Dropped ${info.droppedCount} messages`);
},
};

const properties = {
maxMessages: 100,
bufferMessages: true,
oldMessageLimit: 50,
realtimeOverflow: Constants.RealtimeOverflow.QUEUE,
maxQueue: 70,
newMessageLimit: 20,
};

// destructure publish method and messages from usePubSub hook
const { publish, messages } = usePubSub("CHAT", listeners, properties);

const handlePublishMessage = () => {
// publish message
const message = "Hello Everyone!";
try {
await publish(message, { persist: true });
} catch (e) {
console.log("Error while sending message through pubsub", e);
}
};

return (
<>
<button onClick={handlePublishMessage}>Publish Message</button>
<p>Messages: </p>
{messages.map((message) => {
return (
<p>
{message.senderName} says {message.message}
</p>
);
})}
</>
);
}

Errors

publish() throws:

  • ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINED — called before the meeting is joined.
  • ERROR_MEETING_RECONNECTING — the meeting is reconnecting.
  • ERROR_INVALID_PARAMETERmessage is not a string or payload is not an object.
  • PUBSUB_PUBLISH_FAILED — the publish request times out or the server returns an error.

The hook throws (during subscribe / unsubscribe on mount / unmount):

  • ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINED — hook mounted before the meeting is joined.
  • ERROR_MEETING_RECONNECTING — the meeting is reconnecting.
  • ERROR_INVALID_PARAMETER — any listener is not a function, maxQueue was provided while realtimeOverflow is "drop", newMessageLimit is not greater than 0, oldMessageLimit is less than 0, or the underlying subscribe() ran on the same topic with a listener reference that was already registered.
  • PUBSUB_SUBSCRIBE_FAILED / PUBSUB_UNSUBSCRIBE_FAILED — the subscribe or unsubscribe request times out or the server returns an error.

Applications of usePubSub

PubSub is a powerful mechanism that can be employed to enhance the interactive aspects of your meeting experience. Some common use cases for PubSub during a meeting include:

  1. Chat: You can utilise this to develop features, like Private Chat or Group Chat. You can follow our chat integration guide here.
  2. Raise Hand: You can allow attendees to raise their hands at any point during the meeting, informing everyone else that someone has a question or input.
  3. Layout Switching: You can change the meeting's layout for every participant at once during the meeting, such as from Grid layout to Spotlight or from Grid Layout to Sidebar,etc.
  4. Poll: You can make polls, let users respond to them, and display the results at the end of a poll.
  5. Question Answer Session: You can also design interactive features based on a question-and-answer format.

Downloading PubSub Messages

All the messages from PubSub published with persist : true can be downloaded as an .csv file. This file will be accessible in the VideoSDK dashboard and through the Sessions API.

API Reference

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord