Skip to main content

Goal

By the end of this guide you will have a chat interface with a search panel that lets users find messages in a conversation by keyword and scroll to a selected result — using the built-in CometChatSearch component instead of building your own search UI. CometChatSearch already handles the input, debouncing, SDK queries, result rendering, pagination, loading/empty/error states, and keyword highlighting — so you only wire it to your message list.

Prerequisites

  • Completed the Integration Guide
  • A running CometChatProvider setup with valid credentials
  • An existing chat screen using CometChatMessageList and CometChatMessageHeader

Components Used

ComponentPurpose
CometChatSearchBuilt-in search panel — input, message queries, result list, and states
CometChatMessageListDisplays messages and supports goToMessageId for scrolling to a result
CometChatMessageHeaderHeader with a search trigger button
CometChatConversationsSidebar for switching conversations

Step 1: Set up the chat layout with search state

Start with a full chat layout — a conversations sidebar, message panel, and state to control the search panel visibility and the message to jump to. File: App.tsx
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
  CometChatSearch,
  type CometChatSearchMessageClickEvent,
} from "@cometchat/chat-uikit-react";

function ChatWithSearch() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [showSearch, setShowSearch] = useState(false);
  const [goToMessageId, setGoToMessageId] = useState<number | undefined>(undefined);

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

  // Fired by CometChatSearch when a message result is clicked
  function handleMessageClick(event: CometChatSearchMessageClickEvent) {
    setGoToMessageId(event.message.getId());
  }

  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}
              auxiliaryButtonView={
                <button
                  onClick={() => setShowSearch((prev) => !prev)}
                  aria-label="Search messages"
                  style={{ background: "none", border: "none", cursor: "pointer", fontSize: "18px" }}
                >
                  🔍
                </button>
              }
            />
            <div style={{ flex: 1, overflow: "hidden" }}>
              <CometChatMessageList
                user={user ?? undefined}
                group={group ?? undefined}
                goToMessageId={goToMessageId}
              />
            </div>
            <CometChatMessageComposer user={user ?? undefined} group={group ?? undefined} />
          </>
        )}
      </div>

      {/* Built-in search panel, scoped to the open conversation */}
      {showSearch && (user || group) && (
        <div style={{ width: "350px", borderLeft: "1px solid #e0e0e0" }}>
          <CometChatSearch
            searchIn={["messages"]}
            uid={user?.getUid()}
            guid={group?.getGuid()}
            onMessageClicked={handleMessageClick}
            onBack={() => setShowSearch(false)}
          />
        </div>
      )}
    </div>
  );
}

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

export default App;

Step 2: Scope CometChatSearch to the conversation

CometChatSearch is a complete, self-contained search panel — there’s no custom input or result list to build. A few props tailor it to in-conversation message search:
<CometChatSearch
  searchIn={["messages"]}
  uid={user?.getUid()}
  guid={group?.getGuid()}
  onMessageClicked={handleMessageClick}
  onBack={() => setShowSearch(false)}
/>
PropWhat it does
searchIn={["messages"]}Shows only message results (omit it to also search conversations)
uid / guidScopes the search to a single user or group conversation. Pass whichever matches the open chat
onMessageClickedFired when a result is tapped. The event payload is { message, searchKeyword }
onBackFired when the back button is clicked — use it to close the panel
The component handles the search input, debouncing, SDK queries, pagination, and the loading/empty/error states internally. For the full prop list and customization (filter chips, custom result item views, request builders), see the Search component reference.

Step 3: Navigate to a selected search result

When a result is clicked, onMessageClicked gives you the selected message. Pass its ID to CometChatMessageList via the goToMessageId prop — the list scrolls to the matching message and highlights it.
function handleMessageClick(event: CometChatSearchMessageClickEvent) {
  setGoToMessageId(event.message.getId());
}

<CometChatMessageList
  user={user ?? undefined}
  group={group ?? undefined}
  goToMessageId={goToMessageId}
/>
Reset goToMessageId to undefined when switching conversations (as in handleConversationClick above) so the list doesn’t try to jump to a message ID from a previous chat.

Next Steps

  • Search — full CometChatSearch reference: filters, scopes, custom result views, and request builders
  • Message List — configure message rendering and scroll behavior
  • Message Header — customize header actions and auxiliary views
  • Threaded Messages — add threaded replies to your chat