> ## 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.

# Threaded Messages

> Add threaded message replies to your chat so users can create focused sub-conversations on any message.

## Goal

By the end of this guide you will have a chat interface where users can open a thread panel from any message, view the parent message with its reply count, browse threaded replies, and send new replies — all using v7 compound components and a state-based approach (no custom events needed).

## Prerequisites

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

## Components Used

| Component                  | Purpose                                                                                              |
| :------------------------- | :--------------------------------------------------------------------------------------------------- |
| `CometChatThreadHeader`    | Displays the parent message and reply count at the top of the thread panel                           |
| `CometChatMessageList`     | Renders threaded replies when given a `parentMessageId`                                              |
| `CometChatMessageComposer` | Sends replies into the thread with `parentMessageId`, `layout="compact"`, and `enableRichTextEditor` |

## Step 1: Thread State Management

Store the `threadedMessage` in state. When set, the thread panel renders. When cleared, it closes. This mirrors the pattern used in the sample app's `CometChatThreadPanel` component.

*File: ChatWithThreads.tsx*

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

function ChatWithThreads() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [threadedMessage, setThreadedMessage] = useState<CometChat.BaseMessage | null>(null);

  // Thread opens when threadedMessage is set, closes when cleared
}
```

## Step 2: Wire the Thread Trigger

Use the `onThreadRepliesClick` callback on `CometChatMessageList` to capture when a user clicks "Reply in Thread." This sets the threaded message and opens the panel — no events required.

*File: ChatWithThreads.tsx*

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

<CometChatMessageList
  user={user ?? undefined}
  group={group ?? undefined}
  onThreadRepliesClick={(message) => setThreadedMessage(message)}
/>
```

## Step 3: Build the Thread Panel

When `threadedMessage` is set, render a side panel composing `CometChatThreadHeader` + `CometChatMessageList` (with `parentMessageId`) + `CometChatMessageComposer` (with `parentMessageId`, `layout="compact"`, and `enableRichTextEditor`). The `onClose` callback clears the state to dismiss the panel.

*File: ChatWithThreads.tsx*

```tsx theme={null}
import {
  CometChatThreadHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";

{threadedMessage && (
  <div style={{ width: "400px", borderLeft: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
    <CometChatThreadHeader
      parentMessage={threadedMessage}
      onClose={() => setThreadedMessage(null)}
      onParentDeleted={() => setThreadedMessage(null)}
    />

    <div style={{ flex: 1, overflow: "hidden" }}>
      <CometChatMessageList
        parentMessageId={threadedMessage.getId()}
        user={user ?? undefined}
        group={group ?? undefined}
      />
    </div>

    <CometChatMessageComposer
      parentMessageId={threadedMessage.getId()}
      user={user ?? undefined}
      group={group ?? undefined}
      layout="compact"
      enableRichTextEditor
    />
  </div>
)}
```

## Step 4: Handle Parent Deleted

Use the `onParentDeleted` prop on `CometChatThreadHeader` to automatically close the thread panel when the parent message is deleted by another user or a moderation action.

*File: ChatWithThreads.tsx*

```tsx theme={null}
<CometChatThreadHeader
  parentMessage={threadedMessage}
  onClose={() => setThreadedMessage(null)}
  onParentDeleted={() => setThreadedMessage(null)}
/>
```

## Complete Example

*File: App.tsx*

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

function ChatWithThreads() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [threadedMessage, setThreadedMessage] = useState<CometChat.BaseMessage | null>(null);

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

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

      {/* Main message 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}
                onThreadRepliesClick={(message) => setThreadedMessage(message)}
              />
            </div>
            <CometChatMessageComposer user={user ?? undefined} group={group ?? undefined} />
          </>
        )}
      </div>

      {/* Thread panel */}
      {threadedMessage && (
        <div style={{ width: "400px", borderLeft: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
          <CometChatThreadHeader
            parentMessage={threadedMessage}
            onClose={() => setThreadedMessage(null)}
            onParentDeleted={() => setThreadedMessage(null)}
          />
          <div style={{ flex: 1, overflow: "hidden" }}>
            <CometChatMessageList
              parentMessageId={threadedMessage.getId()}
              user={user ?? undefined}
              group={group ?? undefined}
            />
          </div>
          <CometChatMessageComposer
            parentMessageId={threadedMessage.getId()}
            user={user ?? undefined}
            group={group ?? undefined}
            layout="compact"
            enableRichTextEditor
          />
        </div>
      )}
    </div>
  );
}

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

export default App;
```

## Next Steps

* [Thread Header](/ui-kit/react/components/thread-header) — customize the thread header appearance
* [Message List](/ui-kit/react/components/message-list) — configure message list rendering and options
* [CometChatProvider](/ui-kit/react/cometchat-provider) — learn about provider configuration
