Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cometchat-22654f5b-react-uikit-v7.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

{
  "component": "CometChatPaginatedList",
  "package": "@cometchat/chat-uikit-react",
  "import": "import { CometChatPaginatedList } from \"@cometchat/chat-uikit-react\";",
  "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";",
  "description": "A reusable base component for rendering any SDK entity list with infinite scroll pagination, fetch lifecycle states, and automatic connection recovery.",
  "cssRootClass": ".cometchat-paginated-list",
  "primaryOutput": {
    "prop": "onItemClick",
    "type": "(item: T) => void"
  },
  "props": {
    "data": {
      "requestBuilder": { "type": "CometChat.*RequestBuilder", "default": "—" },
      "list": { "type": "T[]", "default": "[]" },
      "searchKeyword": { "type": "string", "default": "''" }
    },
    "callbacks": {
      "onItemClick": { "type": "(item: T) => void", "default": "—" },
      "onError": { "type": "(error: unknown) => void", "default": "—" },
      "onEmpty": { "type": "() => void", "default": "—" },
      "onScrollToBottom": { "type": "() => void", "default": "—" }
    },
    "behavior": {
      "fetchState": { "type": "'idle' | 'loading' | 'loaded' | 'error' | 'empty'", "default": "'idle'" },
      "hasMore": { "type": "boolean", "default": "true" },
      "showScrollbar": { "type": "boolean", "default": "false" }
    },
    "viewSlots": {
      "itemView": { "type": "(item: T, index: number) => ReactNode", "default": "—" },
      "loadingView": { "type": "ReactNode", "default": "—" },
      "errorView": { "type": "ReactNode", "default": "—" },
      "emptyView": { "type": "ReactNode", "default": "—" },
      "headerView": { "type": "ReactNode", "default": "—" },
      "footerView": { "type": "ReactNode", "default": "—" }
    }
  },
  "events": [],
  "sdkListeners": ["onConnected"],
  "types": {
    "CometChatFetchState": "'idle' | 'loading' | 'loaded' | 'error' | 'empty'"
  }
}

Where It Fits

CometChatPaginatedList is the generic list foundation used internally by CometChatConversations, CometChatUsers, CometChatGroups, CometChatGroupMembers, and CometChatCallLogs. It handles the common pagination machinery — infinite scroll detection, fetch lifecycle states, and SDK reconnection recovery — so that feature components focus only on their domain logic. Use it directly when building a custom list that fetches from any CometChat SDK request builder, or when creating a list of custom entities that follow the same pagination pattern.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatProvider, CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function UserList() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatProvider appId="APP_ID" region="REGION" authKey="AUTH_KEY">
      <CometChatPaginatedList<CometChat.User>
        requestBuilder={builder}
        itemView={(user) => (
          <div style={{ padding: "8px 16px" }}>
            {user.getName()}
          </div>
        )}
        onItemClick={(user) => console.log("Selected:", user.getUid())}
      />
    </CometChatProvider>
  );
}

export default UserList;

Minimal Render

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => <div>{user.getName()}</div>}
    />
  );
}
Root CSS class: .cometchat-paginated-list

Filtering / Data Configuration

SDK Request Builder

Pass any CometChat SDK request builder to requestBuilder. The component calls .build() internally and paginates using fetchNext(). Pass the builder instance — not the result of .build().
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function FilteredGroupMembers() {
  const builder = new CometChat.GroupMembersRequestBuilder("group-id")
    .setLimit(50)
    .setSearchKeyword("john");

  return (
    <CometChatPaginatedList<CometChat.GroupMember>
      requestBuilder={builder}
      itemView={(member) => <div>{member.getName()}{member.getScope()}</div>}
    />
  );
}

Compatible Request Builders

BuilderEntity Type
CometChat.UsersRequestBuilderCometChat.User
CometChat.GroupsRequestBuilderCometChat.Group
CometChat.GroupMembersRequestBuilderCometChat.GroupMember
CometChat.ConversationsRequestBuilderCometChat.Conversation
CometChat.MessagesRequestBuilderCometChat.BaseMessage
CometChat.CallLogRequestBuilderCometChat.CallLog

External Data (Static List)

If you have a pre-fetched array, pass it via list instead of requestBuilder. The component renders the items without pagination.
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

interface CustomItem {
  id: string;
  name: string;
}

function StaticList() {
  const items: CustomItem[] = [
    { id: "1", name: "Alice" },
    { id: "2", name: "Bob" },
    { id: "3", name: "Charlie" },
  ];

  return (
    <CometChatPaginatedList<CustomItem>
      list={items}
      itemView={(item) => <div>{item.name}</div>}
    />
  );
}

Actions and Events

Callback Props

onItemClick

Fires when a list item is clicked.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ClickableList() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => <div>{user.getName()}</div>}
      onItemClick={(user) => console.log("Clicked:", user.getUid())}
    />
  );
}

onError

Fires when a fetch fails or an SDK operation errors.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ListWithErrorHandling() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => <div>{user.getName()}</div>}
      onError={(error) => console.error("Fetch failed:", error)}
    />
  );
}

onEmpty

Fires when the list is empty after the initial fetch completes.

onScrollToBottom

Fires when the user scrolls to the bottom sentinel. Useful for analytics or triggering external side effects.

Fetch Lifecycle States

The component manages an internal fetch state machine. The fetchState reflects the current status:
StateMeaningUI Rendered
idleNot yet started fetchingNothing (initial mount)
loadingA fetch is in progressloadingView or default shimmer
loadedAt least one page fetched successfullyItem list
errorThe last fetch failederrorView or default error
emptyFetch completed but returned zero itemsemptyView or default empty
State transitions:
idle → loading → loaded (has more) → loading → loaded (exhausted)
                                   ↘ error

Infinite Scroll Sentinel

The component uses an IntersectionObserver on a sentinel element at the bottom of the list. When the sentinel enters the viewport (with a 200px root margin), the next page is fetched automatically. No scroll event listeners are used.

Connection Recovery

When the CometChat SDK reconnects after a network drop, the component automatically:
  1. Re-creates the internal request from the builder
  2. Resets the list state
  3. Re-fetches from the first page
This ensures the list is always fresh after connectivity issues — no stale data is displayed.

SDK Events (Real-Time, Automatic)

SDK ListenerInternal Behavior
onConnectedResets state and re-fetches the entire list from scratch

Custom View Slots

SlotSignatureReplaces
itemView(item: T, index: number) => ReactNodeDefault item rendering
headerViewReactNodeArea above the list
footerViewReactNodeArea below the list
loadingViewReactNodeDefault loading shimmer
errorViewReactNodeDefault error message
emptyViewReactNodeDefault empty state

Custom Loading State

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ListWithCustomLoading() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => <div>{user.getName()}</div>}
      loadingView={
        <div style={{ padding: 40, textAlign: "center" }}>
          <span>Loading users...</span>
        </div>
      }
    />
  );
}

Custom Empty State

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ListWithCustomEmpty() {
  const builder = new CometChat.UsersRequestBuilder()
    .setLimit(30)
    .setSearchKeyword("nonexistentuser");

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => <div>{user.getName()}</div>}
      emptyView={
        <div style={{ padding: 40, textAlign: "center" }}>
          <p>No results found. Try a different search.</p>
        </div>
      }
    />
  );
}

Common Patterns

Search with debounced re-fetch

When the requestBuilder reference changes, the component resets and re-fetches. Combine with a debounced search input to build live search.
import { useState, useMemo } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function SearchableUserList() {
  const [keyword, setKeyword] = useState("");

  const builder = useMemo(() => {
    const b = new CometChat.UsersRequestBuilder().setLimit(30);
    if (keyword) b.setSearchKeyword(keyword);
    return b;
  }, [keyword]);

  return (
    <div>
      <input
        type="text"
        placeholder="Search users..."
        value={keyword}
        onChange={(e) => setKeyword(e.target.value)}
        style={{ padding: 8, width: "100%", marginBottom: 8 }}
      />
      <CometChatPaginatedList<CometChat.User>
        requestBuilder={builder}
        itemView={(user) => <div style={{ padding: "8px 16px" }}>{user.getName()}</div>}
      />
    </div>
  );
}

Custom item with avatar

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList, CometChatAvatar } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function UserListWithAvatar() {
  const builder = new CometChat.UsersRequestBuilder().setLimit(30);

  return (
    <CometChatPaginatedList<CometChat.User>
      requestBuilder={builder}
      itemView={(user) => (
        <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "8px 16px" }}>
          <CometChatAvatar image={user.getAvatar()} name={user.getName()} />
          <div>
            <div style={{ fontWeight: 500 }}>{user.getName()}</div>
            <div style={{ fontSize: 12, color: "var(--cometchat-text-color-secondary)" }}>
              {user.getStatus()}
            </div>
          </div>
        </div>
      )}
      onItemClick={(user) => console.log("Selected:", user.getName())}
    />
  );
}
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatPaginatedList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ListWithHeaderFooter() {
  const builder = new CometChat.GroupsRequestBuilder().setLimit(20);

  return (
    <CometChatPaginatedList<CometChat.Group>
      requestBuilder={builder}
      headerView={<h3 style={{ padding: "12px 16px", margin: 0 }}>My Groups</h3>}
      footerView={<div style={{ padding: 12, textAlign: "center", fontSize: 12 }}>End of list</div>}
      itemView={(group) => (
        <div style={{ padding: "8px 16px" }}>
          {group.getName()} ({group.getMembersCount()} members)
        </div>
      )}
    />
  );
}

CSS Architecture

The component uses CSS custom properties from @cometchat/chat-uikit-react/css-variables.css.

Key Selectors

TargetSelector
Root.cometchat-paginated-list
Scrollable container.cometchat-paginated-list__scroll-container
List content area.cometchat-paginated-list__content
Item wrapper.cometchat-paginated-list__item
Header slot.cometchat-paginated-list__header
Footer slot.cometchat-paginated-list__footer
Infinite scroll sentinel.cometchat-paginated-list__sentinel
Loading state.cometchat-paginated-list__loading-state
Error state.cometchat-paginated-list__error-state
Empty state.cometchat-paginated-list__empty-state

Example: Custom scrollbar and padding

App.css
.cometchat-paginated-list {
  max-height: 600px;
}

.cometchat-paginated-list__scroll-container {
  padding: 0 8px;
}

.cometchat-paginated-list__item {
  border-bottom: 1px solid var(--cometchat-border-color-light);
}

.cometchat-paginated-list__item:last-child {
  border-bottom: none;
}

Props

All props are optional unless noted otherwise.

requestBuilder

SDK request builder for paginated fetching. The component calls .build() internally and uses fetchNext() for pagination. When this prop changes, the list resets and re-fetches from the first page.
TypeCometChat.*RequestBuilder (any SDK builder with fetchNext)
Default

list

A static array of items to render without pagination. Use this instead of requestBuilder when you have pre-fetched data.
TypeT[]
Default[]

itemView

Render function for each item in the list.
Type(item: T, index: number) => ReactNode
Default

onItemClick

Callback fired when a list item is clicked.
Type(item: T) => void
Default

onError

Callback fired when a fetch or SDK operation fails.
Type(error: unknown) => void
Default

onEmpty

Callback fired when the list is empty after the initial fetch.
Type() => void
Default

onScrollToBottom

Callback fired when the scroll sentinel is triggered (user scrolled near the bottom).
Type() => void
Default

searchKeyword

Current search keyword. When changed, the component resets and re-fetches with the new keyword applied to the request builder.
Typestring
Default''

showScrollbar

Show the native scrollbar on the list container.
Typeboolean
Defaultfalse

headerView

Content rendered above the list.
TypeReactNode
Default

footerView

Content rendered below the list.
TypeReactNode
Default

loadingView

Custom loading state content. Rendered when fetchState is 'loading' and the list is empty.
TypeReactNode
DefaultDefault shimmer animation

errorView

Custom error state content. Rendered when fetchState is 'error'.
TypeReactNode
DefaultDefault error message

emptyView

Custom empty state content. Rendered when fetchState is 'empty'.
TypeReactNode
DefaultDefault empty illustration

Events

CometChatPaginatedList does not emit global UI events. All communication happens through callback props.
EventPayloadFires when
onItemClickT (generic item)A list item is clicked
onErrorunknownA fetch or SDK operation fails
onEmptyList is empty after initial fetch
onScrollToBottomScroll sentinel enters viewport

CSS Selectors

TargetSelector
Root container.cometchat-paginated-list
Scrollable area.cometchat-paginated-list__scroll-container
Content wrapper.cometchat-paginated-list__content
Individual item.cometchat-paginated-list__item
Header slot.cometchat-paginated-list__header
Footer slot.cometchat-paginated-list__footer
Sentinel (scroll trigger).cometchat-paginated-list__sentinel
Loading state.cometchat-paginated-list__loading-state
Error state.cometchat-paginated-list__error-state
Empty state.cometchat-paginated-list__empty-state