import {
Channel,
ChannelHeader,
MessageComposer,
MessageList,
} from "stream-chat-react";
const App = () => (
<Channel channel={channel}>
<ChannelHeader />
<MessageList />
<MessageComposer />
</Channel>
);This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13).
ChannelHeader
ChannelHeader renders the active channel title, subtitle, and avatar.
Best Practices
- Keep
ChannelHeaderlightweight and move heavier logic into parent components or hooks. - Let
ChannelHeaderderive the title and image from the active channel unless you need explicit overrides. - Use a custom header only when you need additional controls or a different layout.
- Inject app-owned sidebar controls through
HeaderStartContentif your layout usesChannelListorThreadList. - Do not assume the default header renders
channel.data.subtitle; v14 derives its subtitle from typing state and online/member status.
Basic Usage
Render ChannelHeader inside Channel:
The default title and image come from the same channel-preview helpers used by ChannelList, so direct messages and group channels get synthesized display information automatically.
Default Behavior
By default, ChannelHeader:
- uses
useChannelPreviewInfo()to derivedisplayTitle,displayImage, and group-avatar members - shows
TypingIndicatorHeaderin the subtitle while other users are typing in the active channel - otherwise shows online/member status text from
useChannelHeaderOnlineStatus() - renders
ChannelAvatar, which falls back to a group avatar when enough members are available - renders
HeaderStartContentwhen you provide it throughWithComponents/ComponentContext
UI Customization
You can override the avatar locally and inject app-owned sidebar controls through WithComponents:
import {
Avatar,
Channel,
ChannelHeader,
WithComponents,
type ChannelAvatarProps,
} from "stream-chat-react";
const CustomAvatar = ({ imageUrl, userName }: ChannelAvatarProps) => (
<Avatar imageUrl={imageUrl} size="lg" userName={userName} />
);
const SidebarToggle = () => <button type="button">Toggle sidebar</button>;
<WithComponents overrides={{ HeaderStartContent: SidebarToggle }}>
<Channel channel={channel}>
<ChannelHeader Avatar={CustomAvatar} />
</Channel>
</WithComponents>;If you need to replace the whole header, render your own component instead of ChannelHeader. For example, a custom header can still reuse useChannelPreviewInfo() and TypingIndicatorHeader:
import {
TypingIndicatorHeader,
useChannelPreviewInfo,
useChannelStateContext,
useTypingContext,
} from "stream-chat-react";
const CustomChannelHeader = () => {
const { channel, channelConfig } = useChannelStateContext();
const { typing } = useTypingContext();
const { displayTitle } = useChannelPreviewInfo({ channel });
const hasTyping =
channelConfig?.typing_events !== false &&
Object.values(typing ?? {}).some(({ parent_id }) => !parent_id);
return (
<div className="custom-channel-header">
<div>{displayTitle}</div>
<div>{hasTyping ? <TypingIndicatorHeader /> : "Custom subtitle"}</div>
</div>
);
};Props
| Prop | Description | Type |
|---|---|---|
Avatar | Custom avatar component. It receives the same props as ChannelAvatar. Defaults to ChannelAvatar. | component |
image | Manual image override. When omitted, ChannelHeader uses the current channel display image. | string |
title | Manual title override. When omitted, ChannelHeader uses the current channel display title. | string |