> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-rn-guide-message-privately.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Privately

> Let users send a private one-on-one message to another user directly from within a group chat conversation.

## Goal

By the end of this guide you will have a group chat interface where users can select a group member and open a private one-on-one conversation with them — without leaving the current screen. This is useful for side conversations, follow-ups, or sensitive messages that shouldn't be shared with the entire group.

## Prerequisites

* Completed the [Integration Guide](/ui-kit/react/integration-react) guide
* A running `CometChatProvider` setup with valid credentials
* An existing group chat screen using `CometChatMessageList` and `CometChatMessageComposer`

## Components Used

| Component / API            | Purpose                                                                                      |
| :------------------------- | :------------------------------------------------------------------------------------------- |
| `CometChatMessageList`     | Displays group messages (publishes `ui:open-chat` internally via "Message Privately" option) |
| `CometChatMessageComposer` | Text input for the private conversation                                                      |
| `CometChatMessageHeader`   | Displays user/group info                                                                     |
| `useCometChatEvents`       | Subscribe to `ui:open-chat` event                                                            |
| `ui:open-chat`             | UI event published when user clicks "Message Privately"                                      |

## Step 1: Set up the main layout with provider

Start with a layout that includes a conversations sidebar and a main chat area wrapped in `CometChatProvider`.

```tsx App.tsx theme={null}
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
} from "@cometchat/chat-uikit-react";

function App() {
  return (
    <CometChatProvider>
      <ChatWithPrivateMessaging />
    </CometChatProvider>
  );
}

export default App;
```

## Step 2: Track group and private chat state

Maintain state for the active group conversation and a separate state for the private user when a user initiates a private message.

```tsx ChatWithPrivateMessaging.tsx theme={null}
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function ChatWithPrivateMessaging() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [privateUser, setPrivateUser] = useState<CometChat.User | null>(null);

  // ... continued in next steps
}
```

## Step 3: Handle conversation selection

Connect `CometChatConversations` to switch between user and group chats. When switching conversations, close any open private message panel.

```tsx theme={null}
function handleConversationClick(conversation: CometChat.Conversation) {
  setPrivateUser(null); // close private panel on conversation switch

  const entity = conversation.getConversationWith();
  if (entity instanceof CometChat.User) {
    setUser(entity);
    setGroup(null);
  } else if (entity instanceof CometChat.Group) {
    setGroup(entity);
    setUser(null);
  }
}
```

## Step 4: Initiate a private message from a group member

Use the message header or a custom action to let users pick a group member for private messaging. You can fetch the user from a member click event or from the message sender's info.

```tsx theme={null}
async function handleMessagePrivately(uid: string) {
  try {
    const targetUser = await CometChat.getUser(uid);
    setPrivateUser(targetUser);
  } catch (error) {
    console.error("Failed to fetch user for private messaging:", error);
  }
}
```

## Step 5: Listen for the `ui:open-chat` event

Use `useCometChatEvents` to subscribe to the `ui:open-chat` event, which is published internally when a user clicks "Message Privately" from the context menu. When the event fires, extract the user and open the private panel.

```tsx theme={null}
import { useCometChatEvents } from "@cometchat/chat-uikit-react";
import type { CometChatEvent } from "@cometchat/chat-uikit-react";

useCometChatEvents(
  (event: CometChatEvent) => {
    if (event.type === "ui:open-chat" && event.user) {
      setPrivateUser(event.user);
    }
  },
  [group?.getGuid()]
);
```

## Step 6: Render the private message panel

When `privateUser` is set, show a side panel with a private one-on-one chat. This panel includes a header, message list, and composer scoped to the private user.

```tsx theme={null}
{privateUser && (
  <div style={{ width: "400px", borderLeft: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
    <div style={{ display: "flex", alignItems: "center", padding: "12px", borderBottom: "1px solid #e0e0e0" }}>
      <span style={{ flex: 1, fontWeight: 600 }}>
        Private: {privateUser.getName()}
      </span>
      <button onClick={() => setPrivateUser(null)}>✕</button>
    </div>

    <div style={{ flex: 1, overflow: "hidden" }}>
      <CometChatMessageList user={privateUser} />
    </div>

    <CometChatMessageComposer user={privateUser} />
  </div>
)}
```

## Step 7: Handle edge cases

Consider these scenarios when implementing private messaging from a group:

| Scenario                   | Behavior                                                                    |
| :------------------------- | :-------------------------------------------------------------------------- |
| User messages themselves   | Disable the private message option for the logged-in user's own messages    |
| User is blocked            | Check `getBlockedByMe()` before opening the private panel and show a prompt |
| Private panel already open | Replace the current private user with the newly selected one                |
| Group conversation changes | Close the private panel when switching to a different conversation          |

## Complete Example

```tsx App.tsx theme={null}
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
  useCometChatEvents,
} from "@cometchat/chat-uikit-react";
import type { CometChatEvent } from "@cometchat/chat-uikit-react";

function ChatWithPrivateMessaging() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [privateUser, setPrivateUser] = useState<CometChat.User | null>(null);

  function handleConversationClick(conversation: CometChat.Conversation) {
    setPrivateUser(null);
    const entity = conversation.getConversationWith();
    if (entity instanceof CometChat.User) {
      setUser(entity);
      setGroup(null);
    } else if (entity instanceof CometChat.Group) {
      setGroup(entity);
      setUser(null);
    }
  }

  async function handleMessagePrivately(uid: string) {
    try {
      const targetUser = await CometChat.getUser(uid);
      setPrivateUser(targetUser);
    } catch (error) {
      console.error("Failed to fetch user for private messaging:", error);
    }
  }

  useCometChatEvents(
    (event: CometChatEvent) => {
      if (event.type === "ui:open-chat" && event.user) {
        setPrivateUser(event.user);
      }
    },
    [group?.getGuid()]
  );

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      {/* Conversations sidebar */}
      <div style={{ width: "300px", borderRight: "1px solid #e0e0e0" }}>
        <CometChatConversations onItemClick={handleConversationClick} />
      </div>

      {/* Main chat panel */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
        {(user || group) && (
          <>
            <CometChatMessageHeader user={user ?? undefined} group={group ?? undefined} />
            <div style={{ flex: 1, overflow: "hidden" }}>
              <CometChatMessageList
                user={user ?? undefined}
                group={group ?? undefined}
              />
            </div>
            <CometChatMessageComposer user={user ?? undefined} group={group ?? undefined} />
          </>
        )}
      </div>

      {/* Private message panel */}
      {privateUser && (
        <div style={{ width: "400px", borderLeft: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
          <div style={{ display: "flex", alignItems: "center", padding: "12px", borderBottom: "1px solid #e0e0e0" }}>
            <span style={{ flex: 1, fontWeight: 600 }}>
              Private: {privateUser.getName()}
            </span>
            <button onClick={() => setPrivateUser(null)}>✕</button>
          </div>

          <div style={{ flex: 1, overflow: "hidden" }}>
            <CometChatMessageList user={privateUser} />
          </div>

          <CometChatMessageComposer user={privateUser} />
        </div>
      )}
    </div>
  );
}

function App() {
  return (
    <CometChatProvider>
      <ChatWithPrivateMessaging />
    </CometChatProvider>
  );
}

export default App;
```

## Next Steps

* [Message Composer](/ui-kit/react/components/message-composer) — customize the composer for private chats
* [Conversations](/ui-kit/react/components/conversations) — manage the conversations list
* [Users](/ui-kit/react/components/users) — browse and select users directly
* [CometChatProvider](/ui-kit/react/cometchat-provider) — learn about provider configuration
