> ## 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 live chat messages

> Live, store-backed message stream for a conversation or thread

## Overview

The live, canonical view of a conversation's messages. Results are stored in Redux and kept in sync by `ChatProvider` socket events, so new messages, edits, reactions and reply-count changes appear in real time, and state is shared with `useSendMessage` (optimistic inserts), unread tracking and reconnect catch-up. Can be used for the main message stream or for a specific thread (by passing `parentId`).

<Note>Requires `ChatProvider` in the component tree.</Note>

<Tip>For a read-only or **filtered** query (e.g. "only messages that have replies") that should not be touched by live socket traffic, use [`useFetchManyChatMessages` / `useFetchManyChatMessagesWrapper`](/hooks/chat/messages/use-fetch-many-chat-messages) instead. The live hook intentionally does not take a `filters` prop.</Tip>

## Usage Example

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

function MessageList({ conversationId }: { conversationId: string }) {
  const { messages, loading, hasMore, loadOlder } = useLiveChatMessages({
    conversationId,
  });

  return (
    <div>
      {hasMore && (
        <button onClick={loadOlder} disabled={loading}>
          Load older messages
        </button>
      )}
      {messages.map((msg) => (
        <div key={msg.id}>
          <strong>{msg.user?.name ?? "Deleted user"}</strong>: {msg.content}
        </div>
      ))}
    </div>
  );
}
```

## Props

<ParamField body="conversationId" type="string" required>
  The ID of the conversation to load messages for.
</ParamField>

<ParamField body="parentId" type="string | null">
  When provided, loads thread replies for this parent message ID instead of the main stream. Replies are sorted ascending (oldest first); `loadOlder` fetches newer replies.
</ParamField>

<ParamField body="limit" type="number">
  Number of messages per page. Defaults to `50`.
</ParamField>

<ParamField body="includeFiles" type="boolean">
  When `true`, the server populates the `files` field on each message. Omitted by default to keep payloads small.
</ParamField>

## Returns

<ResponseField name="messages" type="ChatMessage[]">
  The loaded messages in ascending order (oldest first). See [ChatMessage](/data-models/chat-message).
</ResponseField>

<ResponseField name="loading" type="boolean">
  `true` while a fetch is in progress.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  `true` if there are more messages to load.
</ResponseField>

<ResponseField name="loadOlder" type="() => Promise<void>">
  For the main stream: fetches messages older than the oldest currently loaded.
  For threads: fetches replies newer than the newest currently loaded.
  No-ops if `loading` is `true` or `hasMore` is `false`.
</ResponseField>

## Notes

* New messages that arrive via the socket (`message:created`) are appended to the store automatically — no manual refetch needed.
* For integration guidance, see [Chat: Messages](/sdk/chat/messages).
