# Thread list UI

The thread list is the column of threads the user takes part in, shown in the threads view. Each thread list item shows one thread's channel, parent message and latest reply. Use this page to know what `<ThreadList/>` loads and renders, what each thread list item shows and reads, and which parts you can replace. An open thread is on [Thread UI](https://getstream.io/chat/docs/sdk/react/ui/components/thread-ui/). The props are in the [ThreadList](https://getstream.io/chat/docs/sdk/react/component-reference/thread-list/threadlist/) and [ThreadListItem](https://getstream.io/chat/docs/sdk/react/component-reference/thread-list/threadlistitem/) references.

![The thread list, with its parts numbered: the header, the unseen threads banner, the parts of a thread list item, and the open thread](https://getstream.io/docs-assets/images/53b97b1a367d.png)

This is the default thread list, with the Hiking club thread open. Its parts, numbered on the first item:

| Part                                | Explained in                                            |
| ----------------------------------- | ------------------------------------------------------- |
| 1. The header                       | [Header](#header)                                       |
| 2. The unseen threads banner        | [The unseen threads banner](#the-unseen-threads-banner) |
| 3. The latest reply author's avatar | [Thread list items](#thread-list-items)                 |
| 4. The channel's title              | [Thread list items](#thread-list-items)                 |
| 5. The parent message, summarized   | [Thread list items](#thread-list-items)                 |
| 6. The participants' avatars        | [Thread list items](#thread-list-items)                 |
| 7. The reply count                  | [Thread list items](#thread-list-items)                 |
| 8. The latest reply's time          | [Thread list items](#thread-list-items)                 |
| 9. The unread count                 | [Thread list items](#thread-list-items)                 |
| 10. The open thread, selected       | [Thread list items](#thread-list-items)                 |

## The ThreadList component

`<ThreadList/>` renders the threads of `client.threads`, the thread manager. What it does, and when:

| When                                     | `<ThreadList/>`                                                                                                                                                                |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| It mounts                                | Reloads the list                                                                                                                                                               |
| The page is visible                      | Activates `client.threads`, so the list follows new replies                                                                                                                    |
| The page is hidden, or it unmounts       | Deactivates `client.threads`                                                                                                                                                   |
| `client.threads.paginator.state` changes | Renders a `<ThreadListItem/>` for each thread, in the server's order: unread threads first, then by latest reply                                                               |
| The user scrolls to the end              | Loads the next page                                                                                                                                                            |
| The user clicks an item                  | Opens the thread with `openThread(thread)` from `useWorkspaceNavigation()`. Without a layout, this does nothing; see [Navigation](https://getstream.io/chat/docs/sdk/react/ui/layout/navigation/). |
| The user ⌘/ctrl-clicks an item           | Asks the layout to open the thread beside the current one, where the layout has room                                                                                           |

The list is virtualized with `react-virtuoso`; its `virtuosoProps` prop passes props to it. Below the items, it renders the notifications published to the thread list.

## Header

`<ThreadListHeader/>` shows the "Threads" title. `<ThreadList/>` renders it above the items, without props. It takes the same `StartContent` and `EndContent` props as `<ChannelListHeader/>`. Register a component under the `ThreadListHeader` key that renders `<ThreadListHeader/>` with `StartContent` or `EndContent`, as [Channel list UI → Header](https://getstream.io/chat/docs/sdk/react/ui/components/channel-list-ui/#header) shows. To show content only while a thread is open, return `null` from it while `openThreads` from `useWorkspaceNavigation()` is empty.

## Thread list items

Each thread list item is a `<ThreadListItem/>`. It provides its thread to the components inside and renders `ThreadListItemUI`, the item's look, which reads the thread's stores:

| The item shows                      | Read from                                                                                           |
| ----------------------------------- | --------------------------------------------------------------------------------------------------- |
| The latest reply author's avatar    | `thread.messagePaginator.aggregateState`: `latestMessage`                                           |
| The channel's title                 | `thread.state`: `channel`                                                                           |
| The parent message, summarized      | `thread.state`: `parentMessage`                                                                     |
| Up to 3 participants' avatars       | `thread.state`: `participants`                                                                      |
| The reply count                     | `thread.state`: `replyCount`                                                                        |
| The latest reply's time             | `thread.messagePaginator.aggregateState`: `latestMessage`                                           |
| The unread count, when there is one | `thread.state`: `read[userId].unreadMessageCount`                                                   |
| Selected                            | `isThreadActive(thread.id)` from `useWorkspaceNavigation()`: the thread is open                     |
| Highlighted for 2 seconds           | the thread has just come into the list from the [unseen threads banner](#the-unseen-threads-banner) |

Anything rendered inside an item retrieves its thread with `useThreadListItemContext()`. `ThreadListItemUI` renders a button: it takes the button's props, and `accessibleLabelConfig`, which configures the item's accessible name; see the [ThreadListItem reference](https://getstream.io/chat/docs/sdk/react/component-reference/thread-list/threadlistitem/).

### The unseen threads banner

A thread that isn't in the loaded list can get a reply, for example an older thread someone answers. The thread manager records it in `client.threads.state` as unseen, and the list shows a banner above the items: "2 unread threads". Clicking it reloads the list, which brings those threads in at their new position. While it reloads, the banner reads "Loading...".

## Loading, empty and error states

`<ThreadList/>` shows a state of its own while the first page loads, when it fails, while the next page loads, and when it has no threads. [List states UI](https://getstream.io/chat/docs/sdk/react/ui/components/list-states-ui/) lists each state's default and `<WithComponents/>` key, and explains what happens when a query fails.

## Replacing parts

Register replacements with `<WithComponents/>`. [Overriding components](https://getstream.io/chat/docs/sdk/react/ui/components/overriding-components/) explains how overrides apply.

| Component to override (`<WithComponents/>` key)                                                                   | Replaces                                                                                                                |
| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `ThreadListItem`                                                                                                  | The whole item. Gets `thread`.                                                                                          |
| `ThreadListItemUI`                                                                                                | The item's look                                                                                                         |
| `ThreadListUnseenThreadsBanner`                                                                                   | The [unseen threads banner](#the-unseen-threads-banner)                                                                 |
| `FirstPageLoadingIndicator`, `ListLoadErrorIndicator`, `ThreadListLoadingIndicator`, `ThreadListEmptyPlaceholder` | The [loading, error and empty states](https://getstream.io/chat/docs/sdk/react/ui/components/list-states-ui/)                               |
| `ThreadListHeader`                                                                                                | The [list header](#header). Register a component that renders `<ThreadListHeader/>` to keep the default and add content |

The defaults of `ThreadListUnseenThreadsBanner`, `ThreadListEmptyPlaceholder` and `ThreadListLoadingIndicator` aren't exported, so a replacement for one of them can't render the default inside it.

Here is a `ThreadsSidebar` component that keeps the default item and shows the thread's title above it, when the thread has one:

```tsx title="src/ThreadsSidebar.tsx"
import type { ThreadState } from "stream-chat";
import type { ThreadListItemUIProps } from "stream-chat-react";
import {
  ThreadList,
  ThreadListItemUI,
  useStateStore,
  useThreadListItemContext,
  WithComponents,
} from "stream-chat-react";

const titleSelector = ({ title }: ThreadState) => ({ title });

const ItemWithTitle = (props: ThreadListItemUIProps) => {
  const thread = useThreadListItemContext();
  const { title } = useStateStore(thread?.state, titleSelector) ?? {};

  return (
    <div className="thread-list-item-with-title">
      {title && (
        <span className="thread-list-item-with-title__title">{title}</span>
      )}
      <ThreadListItemUI {...props} />
    </div>
  );
};

const overrides = { ThreadListItemUI: ItemWithTitle };

export const ThreadsSidebar = () => (
  <WithComponents overrides={overrides}>
    <ThreadList />
  </WithComponents>
);
```

## Used in

- [Replies and threads](https://getstream.io/chat/docs/sdk/react/features/messaging/replies-and-threads/)
- [Threads view](https://getstream.io/chat/docs/sdk/react/ui-cookbooks/panels/threads-view/)

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/ui/components/thread-list-ui/](https://getstream.io/chat/docs/sdk/react/ui/components/thread-list-ui/).