# ThreadListItem

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

`ThreadListItem` is the override key of a row of [`ThreadList`](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/thread-list/threadlist/). For each thread, the list renders an internal wrapper that subscribes to the thread's stores and provides `ThreadListItemContext`, and the wrapper renders the component registered as `ThreadListItem`. The row gets no props: it reads its thread and the values it shows with `useThreadListItemContext()`. [Thread UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/thread-ui/#the-thread-list) describes what a row shows and which stores it reads.

## Best practices

- Read the row's values from `useThreadListItemContext()`. They follow the thread's state, so the row updates when a reply arrives, and the row doesn't need to query the thread again.
- Open the thread with `onThreadSelect` from `useThreadsContext()`, as the default row does, so the list's prop decides where the thread opens.
- To keep the default row and change one part, replace `ThreadListItemMessagePreview` or `ThreadMessagePreviewDeliveryStatus`. The default row isn't exported, so a replacement row can't render it.
- Keep the row light. Rows mount and unmount as the user scrolls.
- For a value the context doesn't hold, subscribe to `thread.state` with `useStateStore` and a selector declared at module scope.

## What the default row shows

The default row, `ThreadListItemComponent`, is a button that calls `onThreadSelect(thread)`. It shows:

- the avatar of the latest reply's author, with an online mark in a two-member channel whose other member is online;
- the channel's name;
- the parent message, after `ThreadMessagePreviewDeliveryStatus`, or "Draft:" and the draft when the user left text or files in the thread's composer. It shows only when the thread has a reply or a draft;
- the avatars of up to three participants, "1 Reply" or "4 Replies", and the time of the latest reply, or the time the parent message was deleted;
- the user's unread count, unless the parent message was deleted.

The time is today's time, "Yesterday", the weekday for the past week, and the date before that. Its format is the translation key `timestamp.ThreadListItem`; see [Localization](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/localization/).

## UI customization

| Override key                         | Replaces                                                                          | Props                                                      |
| ------------------------------------ | --------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `ThreadListItem`                     | The whole row                                                                     | none; reads `useThreadListItemContext()`                   |
| `ThreadListItemMessagePreview`       | The parent message or the draft in a row                                          | `message: LocalMessage \| MessageResponse \| DraftMessage` |
| `ThreadMessagePreviewDeliveryStatus` | The mark before the parent message: the author, or "You:" and its delivery status | `channel: Channel`, `message: LocalMessage`                |

The default `ThreadListItemMessagePreview` shows the draft from the row's context when there is one, and the `message` otherwise, with an icon for its attachments. The default `ThreadMessagePreviewDeliveryStatus` shows nothing in a channel without a name where the parent's author is the only other member. It shows the author's name when someone else wrote the parent message, and "You:" with a clock, one check or two checks when the user did. Two checks in the accent color mean the message was read, which needs read events on in the channel.

This preview shows the parent message's author before the text:

```tsx title="src/threadListOverrides.tsx"
import { Text } from "react-native";
import type { DraftMessage, LocalMessage, MessageResponse } from "stream-chat";
import {
  useThreadListItemContext,
  type ComponentOverrides,
} from "stream-chat-react-native";

const PreviewWithAuthor = ({
  message,
}: {
  message: LocalMessage | MessageResponse | DraftMessage;
}) => {
  const { draftMessage, parentMessage } = useThreadListItemContext();

  if (draftMessage) {
    return <Text numberOfLines={1}>Draft: {draftMessage.text}</Text>;
  }

  return (
    <Text numberOfLines={1}>
      {parentMessage?.user?.name}: {message.text}
    </Text>
  );
};

// Pass to `WithComponents`, declared once at module scope.
export const threadListOverrides: ComponentOverrides = {
  ThreadListItemMessagePreview: PreviewWithAuthor,
};
```

[Thread UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/thread-ui/#replacing-parts) replaces the whole row, and the [Custom thread list UI cookbook](https://getstream.io/chat/docs/sdk/react-native/v10/ui-cookbook/app/custom-thread-list/) builds a list of its own.

## ThreadListItemContext

| Value                   | Type                            | Description                                                                                                                    |
| ----------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `thread`                | `Thread`                        | The row's thread. Pass it to `onThreadSelect`, or subscribe to `thread.state` for more.                                        |
| `channel`               | `Channel`                       | The thread's channel, from `thread.state`.                                                                                     |
| `parentMessage`         | `LocalMessage \| undefined`     | The parent message, from `thread.state`. Its `reply_count` and `thread_participants` are the counts and avatars the row shows. |
| `lastReply`             | `LocalMessage \| undefined`     | The latest reply, from `thread.messagePaginator.aggregateState`, also when the loaded page of replies isn't the latest.        |
| `ownUnreadMessageCount` | `number`                        | The user's unread replies in the thread, from `thread.state.read`. `0` when there are none.                                    |
| `draftMessage`          | `DraftMessage`                  | The text and files the user left in `thread.messageComposer`, or `undefined` when it's empty.                                  |
| `dateString`            | `string \| number \| undefined` | The time of the latest reply, formatted with `timestamp.ThreadListItem`.                                                       |
| `deletedAtDateString`   | `string \| number \| undefined` | The time the parent message was deleted, formatted the same way, or `undefined`.                                               |

`useThreadListItemContext()` doesn't throw outside a row: it returns an empty object. `ThreadListItemContext`, `ThreadListItemProvider` and the `ThreadListItemContextValue` type are exported, for rendering a row of your own outside `ThreadList` with a value you build.

## Related hooks

| Hook                                    | Returns                                                                                  |
| --------------------------------------- | ---------------------------------------------------------------------------------------- |
| `useThreadListItemContext()`            | the values above, inside a row                                                           |
| `useThreadsContext()`                   | `onThreadSelect` and the list's state                                                    |
| `useStateStore(thread.state, selector)` | a selection of the thread's state: parent message, reply count, participants, read state |
| `useChannelPreviewDisplayName(channel)` | the channel's name, as the default row shows it                                          |

See [useThreadListItemContext](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/state-and-entity-hooks/#usethreadlistitemcontext) and, for the fields of `thread.state`, [Thread and thread manager](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/thread-and-thread-manager/#thread-state).

---

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