# ThreadList

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

`ThreadList` lists the threads the current user takes part in. It reads `client.threads`, the thread manager, and renders one [`ThreadListItem`](https://getstream.io/chat/docs/sdk/react/v15/component-reference/thread-list/threadlistitem/) per thread. [Thread UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/thread-ui/#the-thread-list) describes what it shows, and [Replies and threads](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/replies-and-threads/#the-thread-list) how the list loads and stays current.

## Best practices

- Render it anywhere inside `Chat`. It needs no `Channel`.
- Render one `ThreadList` at a time. Each one reloads the list when it mounts, and deactivates `client.threads` when it unmounts, even while another list is still on screen.
- Change the rows through the `ThreadListItemUI` override key. Keep `ThreadListItem`, which gives each row its thread.
- Keep rows light. The list is virtualized with `react-virtuoso`, so rows mount and unmount as the user scrolls.
- Clicking a row opens the thread through `useWorkspaceNavigation()`. Without a layout that does nothing, so use `ChatView` or provide your own navigation, as in [Threads without ChatView](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/replies-and-threads/#threads-without-chatview).

## Basic usage

```tsx
import { Chat, ThreadList } from "stream-chat-react";

export const ThreadsPage = () => (
  <Chat client={client}>
    <ThreadList />
  </Chat>
);
```

`ThreadList` renders, from top to bottom:

- a header with the "Threads" title, and the `HeaderEndContent` override at its end while a thread is open;
- `ThreadListUnseenThreadsBanner`, while threads outside the list have new replies;
- the rows, a `ThreadListItem` for each thread in `client.threads.paginator`;
- `ThreadListLoadingIndicator` after the last row while the next page loads, or `ThreadListEmptyPlaceholder` when there are no threads;
- a `NotificationList` for the `thread-list` panel.

While the first page loads, it shows placeholder rows instead.

## Selection in a ChatView workspace

With `ChatView`, render `ThreadList` in the threads view, next to a `ThreadSlot`. Clicking a row calls `openThread(thread)`, and `ChatView` puts the thread in the view's thread slot. ⌘/ctrl-click asks the layout to open it beside the open one. The row of an open thread is marked with `aria-selected`.

```tsx
import {
  MessageComposer,
  MessageList,
  ThreadHeader,
  ThreadList,
} from "stream-chat-react";
import { ChatView, ThreadSlot } from "stream-chat-react/slot-layout";

// Pass it to ChatView as `views={{ threads: <ThreadsView /> }}`, with a
// "thread" slot in the threads layout.
export const ThreadsView = () => (
  <>
    <ChatView.Selector />
    <ThreadList />
    <ThreadSlot slot="thread">
      <ThreadHeader />
      <MessageList />
      <MessageComposer />
    </ThreadSlot>
  </>
);
```

The [Quick start](https://getstream.io/chat/docs/sdk/react/v15/getting-started/quick-start/#add-threads) builds the whole layout, and [Workspace with ChatView](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/) explains views and slots.

## Override keys

`ThreadList` reads these keys from `WithComponents`. [Thread UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/thread-ui/#replacing-parts) shows a replacement row.

| Override key                    | Replaces                                           | Props                   |
| ------------------------------- | -------------------------------------------------- | ----------------------- |
| `ThreadListItem`                | The whole row                                      | `ThreadListItemProps`   |
| `ThreadListItemUI`              | The row's look, inside `ThreadListItem`            | `ThreadListItemUIProps` |
| `ThreadListUnseenThreadsBanner` | The banner that reloads the list                   | none                    |
| `ThreadListLoadingIndicator`    | The spinner after the last row                     | none                    |
| `ThreadListEmptyPlaceholder`    | What shows when there are no threads               | none                    |
| `HeaderEndContent`              | The end of the list header, while a thread is open | none                    |
| `NotificationList`              | The notifications shown over the list              | `NotificationListProps` |

## Props

| Prop            | Type                             | Default | Description                                                                                                                                                                                                             |
| --------------- | -------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `virtuosoProps` | `VirtuosoProps<Thread, unknown>` | none    | Props for the underlying [`Virtuoso`](https://virtuoso.dev/virtuoso-api/interfaces/VirtuosoProps/) list. They're applied last, so they replace the SDK's own, such as `atBottomStateChange`, which loads the next page. |

## Related hooks

| Hook                         | Returns                                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| `useThreadList()`            | nothing. Reloads `client.threads` and keeps it active while the page is visible. `ThreadList` calls it. |
| `useThreadListItemContext()` | the thread of the row being rendered, or `undefined` outside a row                                      |
| `useWorkspaceNavigation()`   | `openThread` and `isThreadActive`, which the rows use to open a thread and mark the open one            |

The thread list's own stores have no hook. Read `client.threads.paginator.state` for the threads and `client.threads.state` for `unreadThreadCount` and `unseenThreadIds` with `useStateStore`. See [useThreadList](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/loading-data-hooks/#usethreadlist), [useThreadListItemContext](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/state-and-entity-hooks/#usethreadlistitemcontext) and [Thread and thread manager](https://getstream.io/chat/docs/sdk/react/v15/reference/state/thread-and-thread-manager/).

---

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