Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

Thread

Thread gives one thread to the components inside it and renders only them, in a str-chat__thread container. Thread UI explains what it does, and Replies and threads covers the feature.

Best practices

  • Get the thread from client.threads.ensure({ channel, parentMessage }) or client.threads.get(id), never from new Thread(). The client keeps one instance per thread and sends it its events.
  • Compose the panel from children. Thread renders no header, message list or composer of its own.
  • With ChatView, render ThreadSlot. It renders Thread for the thread in its slot, around the same children.
  • A Thread needs no Channel around it. Inside it, useChannel() returns the thread's channel.
  • For long threads, render VirtualizedMessageList inside instead of MessageList.

Basic usage

This panel opens the thread of a message:

import { useMemo } from "react";
import type { Channel as StreamChannel, LocalMessage } from "stream-chat";
import {
  MessageComposer,
  MessageList,
  Thread,
  ThreadHeader,
  useChatContext,
} from "stream-chat-react";

type ThreadPanelProps = {
  channel: StreamChannel;
  parentMessage: LocalMessage;
};

export const ThreadPanel = ({ channel, parentMessage }: ThreadPanelProps) => {
  const { client } = useChatContext();
  // Returns the thread the client already has for this message, or creates it.
  const thread = useMemo(
    () => client.threads.ensure({ channel, parentMessage }),
    [channel, client, parentMessage],
  );

  return (
    <Thread thread={thread}>
      <ThreadHeader />
      <MessageList />
      <MessageComposer />
    </Thread>
  );
};

MessageList renders the parent message above the replies, and MessageComposer writes into thread.messageComposer. Thread loads the thread while its state is stale. It renders nothing until the thread has its parent message, and nothing when replies are off for the channel.

Without a layout, the replies button on a message opens nothing. Threads without ChatView keeps the open thread in state and renders this panel for it.

UI customization

Thread and ThreadHeader have no override key. Change the panel by changing its children, and the header through its props, below.

Two parts of the panel are override keys. The message list renders both:

Override key Replaces Props
ThreadHead The parent message, above the replies MessageProps, with the parent as message
ThreadStart The reply count under the parent message none

The default ThreadStart is exported, so a replacement can render it. The default ThreadHead isn't. Replies and threads replaces ThreadStart.

Inside a thread, the message list and the composer take the same override keys as in a channel. To give the thread a message UI of its own, register it inside Thread, so it applies only there:

import type { Thread as StreamThread } from "stream-chat";
import {
  MessageComposer,
  MessageList,
  MessageText,
  Thread,
  ThreadHeader,
  WithComponents,
} from "stream-chat-react";

const CompactReply = () => (
  <div className="compact-reply">
    <MessageText />
  </div>
);

const threadOverrides = { MessageUI: CompactReply };

export const CompactThread = ({ thread }: { thread: StreamThread }) => (
  <Thread thread={thread}>
    <WithComponents overrides={threadOverrides}>
      <ThreadHeader />
      <MessageList />
      <MessageComposer />
    </WithComponents>
  </Thread>
);

To change the container's class names, set customClasses.thread on Chat. It replaces str-chat__thread-container str-chat__thread.

Props

Prop Type Default Description
thread Thread required The thread to render, a Thread from stream-chat. Get it from client.threads.ensure() or client.threads.get().
children ReactNode none The panel: usually ThreadHeader, MessageList and MessageComposer.

ThreadHeader props

ThreadHeader shows "Thread" with a subtitle, the channel's name and the reply count, or who is typing. Thread UI describes it, and the Thread header recipe builds one of your own.

Prop Type Default Description
StartContent React.ComponentType WorkspaceNavigationBackButton Rendered at the start. The default back button shows only while the thread is stacked over other content in its panel.
EndContent React.ComponentType WorkspaceNavigationCloseButton Rendered at the end. The default close button shows only while the thread's panel can be closed.
overrideTitle string the channel's name Replaces the channel's name in the subtitle.

A component passed as StartContent or EndContent replaces the button. Render the button inside it to keep it.

Hook Returns
useThreadContext() the thread of the nearest Thread, or undefined outside one
useChannel() inside a thread, the thread's channel
useMessageComposerController() inside a thread, thread.messageComposer
useCloseThread() a function that closes the thread in context through workspace navigation

See ThreadContext and useThreadContext. With ChatView, ThreadSlot and its props are on ChatView components.