> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sublay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Use entity comments

> Load and page through an entity's top-level comments, with optional nested replies

## Overview

`useEntityComments` is a lower-level hook that loads an entity's top-level comments, cursor-paginated, with optional nested replies. It is used internally by `CommentSectionProvider`. Use it directly when you need the comment list without the rest of the provider (reply state, comment creation, highlighted comments).

<Note>
  For most use cases, use `CommentSectionProvider` + `useCommentSection` instead. See [Comment Section](/v8/sdk/comments/comment-section). Replies loaded through [`useReplies`](/v8/hooks/comments/use-replies) require the provider.
</Note>

## Usage Example

```tsx theme={null}
import { useEntityComments } from "@sublay/react-js";

function CommentList({ entityId }: { entityId: string }) {
  const { comments, loading, error, hasMore, loadMore } = useEntityComments({
    entityId,
    defaultSortBy: "top",
  });

  // Nothing loaded yet: offer a retry. loadMore() re-sends the failed page.
  if (error && comments.length === 0) {
    return (
      <>
        <p>Couldn't load comments.</p>
        <button onClick={() => loadMore()}>Try again</button>
      </>
    );
  }

  return (
    <>
      {comments.map((c) => <div key={c.id}>{c.content}</div>)}
      {hasMore && (
        <button onClick={() => loadMore()} disabled={loading}>
          Load more
        </button>
      )}
    </>
  );
}
```

## Props

<ParamField path="entityId" type="string | null | undefined" required>
  The entity whose comments to load. Nothing is fetched until it's set.
</ParamField>

<ParamField path="limit" type="number">
  Top-level comments per page. Default: `10`.
</ParamField>

<ParamField path="defaultSortBy" type="CommentsSortByOptions">
  Initial sort: `"createdAt"`, `"top"` or `"controversial"`. Default: `"createdAt"`. Changeable at runtime with `setSortBy`. `"new"` / `"old"` are deprecated aliases for `"createdAt"`.
</ParamField>

<ParamField path="defaultSortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">
  Initial sort direction; applies to every sort. Default: `"desc"`. Changeable with `setSortDir`.
</ParamField>

<ParamField path="defaultSortByReaction" type="ReactionType">
  The reaction `"top"` ranks by (raw count). Server default: `"upvote"`. Changeable with `setSortByReaction`.
</ParamField>

<ParamField path="replyDepth" type="number">
  Levels of replies to nest under every top-level comment, on every page (`0`–`5`). Default: `0` — replies load on demand through `useReplies`.
</ParamField>

<ParamField path="replyLimit" type="number">
  Replies per comment in the nested levels. Default: `3`.
</ParamField>

<ParamField path="replySortBy" type="CommentReplySortByOptions">
  Sort for replies: `"createdAt"`, `"top"` or `"controversial"`. Defaults to the current sort. Not changeable at runtime.
</ParamField>

<ParamField path="replySortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">
  Sort direction for replies. Defaults to the current sort direction. Not changeable at runtime.
</ParamField>

<ParamField path="replySortByReaction" type="ReactionType">
  The reaction replies rank by when their sort is `"top"`. Defaults to the current `sortByReaction` when the section is also sorted by `"top"`, else `"upvote"`. Not changeable at runtime.
</ParamField>

<ParamField path="include" type="&#x22;user&#x22; | &#x22;grants&#x22; | (&#x22;user&#x22; | &#x22;grants&#x22;)[]">
  Related data to populate, at every level. Default: `"user"`.
</ParamField>

A page can return at most 500 comments, nested replies included (see [Request size limit](/v8/api-reference/comments/fetch-many-comments#request-size-limit)). The hook sends `limit`, `replyDepth` and `replyLimit` as given; a combination over the limit fails with an error in `error`, and a development build logs which values to lower.

## Return Values

<ResponseField name="comments" type="Comment[]">
  Loaded top-level comments, in sort order (not including ones added this session).
</ResponseField>

<ResponseField name="newComments" type="Comment[]">
  Always empty when the hook is used on its own: it has no way to add a comment. Inside `CommentSectionProvider` the same field holds the top-level comments posted this session (see [`useCommentSection`](/v8/sdk/comments/comment-section#usecommentsection-return-values)).
</ResponseField>

<ResponseField name="loading" type="boolean">
  `true` while a page is loading, and while `entityId` isn't set. When `entityId` changes, `comments` is empty and `loading` is `true` from the first render with the new id.
</ResponseField>

<ResponseField name="error" type="Error | null">
  The last failure loading the list. Cleared when the next load starts. Call `loadMore()` to retry — `hasMore` stays `true` after a failure, and the retry asks for the same page again, including a first page that failed.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  `true` when more top-level comments are available.
</ResponseField>

<ResponseField name="loadMore" type="() => Promise<void>">
  Loads the next page of top-level comments, or retries the page that failed. Does nothing while a page is loading or when `hasMore` is `false`, and never throws — failures land in `error`.
</ResponseField>

<ResponseField name="getComment" type="(commentId: string) => Comment | undefined">
  A loaded comment by ID — top-level or a reply — without its nested `replies`.
</ResponseField>

<ResponseField name="sortBy" type="CommentsSortByOptions">
  Current sort.
</ResponseField>

<ResponseField name="setSortBy" type="(newSortBy: CommentsSortByOptions) => void">
  Changes the sort and reloads from the first page.
</ResponseField>

<ResponseField name="sortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">
  Current sort direction.
</ResponseField>

<ResponseField name="setSortDir" type="(newSortDir: &#x22;asc&#x22; | &#x22;desc&#x22;) => void">
  Changes the sort direction and reloads from the first page.
</ResponseField>

<ResponseField name="sortByReaction" type="ReactionType | undefined">
  The reaction `"top"` ranks by. Only sent with `sortBy: "top"`.
</ResponseField>

<ResponseField name="setSortByReaction" type="(newReaction: ReactionType | undefined) => void">
  Changes the ranking reaction. While `sortBy` is `"top"` this reloads from the first page; under any other sort the value is kept for later and nothing reloads.
</ResponseField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.