ThreadListItem
ThreadListItem is the override key of a row of 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 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
onThreadSelectfromuseThreadsContext(), 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
ThreadListItemMessagePrevieworThreadMessagePreviewDeliveryStatus. 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.statewithuseStateStoreand 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.
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:
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 replaces the whole row, and the Custom thread list UI cookbook 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 and, for the fields of thread.state, Thread and thread manager.