import {
Chat,
Channel,
ChannelList,
Window,
ChannelHeader,
MessageList,
MessageInput,
Thread,
useCreateChatClient,
} from "stream-chat-react";
import "stream-chat-react/dist/css/v2/index.css";
const apiKey = "your-api-key";
const userId = "user-id";
const token = "authentication-token";
const filters = { members: { $in: [userId] }, type: "messaging" };
const options = { presence: true, state: true };
const sort = { last_message_at: -1 };
const App = () => {
const client = useCreateChatClient({
apiKey,
tokenOrProvider: token,
userData: { id: userId },
});
if (!client) return <div>Loading...</div>;
return (
<Chat client={client}>
<ChannelList sort={sort} filters={filters} options={options} />
<Channel>
<Window>
<ChannelHeader />
<MessageList />
<MessageInput />
</Window>
<Thread />
</Channel>
</Chat>
);
};Getting Started
This section gives a high-level overview of setup, core components, and how they fit together. For a full step-by-step React app setup, see the React Chat tutorial.
Best Practices
- Follow the tutorial once end-to-end before diverging into custom layouts.
- Keep
ChatandChannelas the top-level providers to ensure contexts flow correctly. - Use
useCreateChatClientfor lifecycle management; avoid manual connect/disconnect logic. - Start with default components and override selectively to minimize custom surface area.
- Define channel types and permissions early so UI behavior matches server rules.
Your First App with Stream Chat React
Before starting, install stream-chat-react (and stream-chat) as described in Installation.
You’ll also need to create a Stream Chat app and generate a user token.
The example below is the minimum code to render a working chat UI.
The Chat and Channel components are React context providers. They pass UI, state, and action handlers to their children.
To organize the components in a chat messenger layout, you can start with the following SCSS:
html,
body,
#root {
margin: unset;
padding: unset;
height: 100%;
}
#root {
display: flex;
height: 100%;
.str-chat__channel-list {
position: fixed;
z-index: 1;
height: 100%;
width: 0;
flex-shrink: 0;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
&--open {
width: 30%;
position: fixed;
}
transition: width 0.3s ease-out;
}
.str-chat__channel {
flex: 1;
min-width: 0;
}
.str-chat__main-panel {
min-width: 0;
flex: 1;
&--thread-open {
display: none;
}
}
.str-chat__thread {
flex: 1;
height: 100%;
position: fixed;
z-index: 1;
}
.str-chat__channel-header .str-chat__header-hamburger {
width: 30px;
height: 38px;
padding: var(--xxs-p);
margin-right: var(--xs-m);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: none;
background: transparent;
&:hover {
svg path {
fill: var(--primary-color);
}
}
}
@media screen and (min-width: 768px) {
.str-chat__channel-list {
width: 30%;
position: initial;
z-index: 0;
}
.str-chat__thread {
position: initial;
z-index: 0;
}
.str-chat__channel-header .str-chat__header-hamburger {
display: none;
}
}
@media screen and (min-width: 1024px) {
.str-chat__main-panel {
min-width: 0;
&--thread-open {
max-width: 55%;
display: flex;
}
}
.str-chat__thread {
max-width: 45%;
}
.str-chat__channel-header .str-chat__header-hamburger {
display: none;
}
}
}Chat Client & Connecting User
To communicate with the Stream Chat API the SDK requires a client with an established connection.
The
useCreateChatClienthook instantiates the client, connects the user, and cleans up on unmount.
The useCreateChatClient hook accepts an options object forwarded to the StreamChat constructor. The client is not recreated when options changes. If you need to re-create it, set a key on the component that calls the hook:
import { Chat, StreamChatOptions, useCreateChatClient } from 'stream-chat-react';
const App = () => {
const [timeout, setTimeout] = useState(6000);
const key = `timeout_${timeout}`;
return <ChatWithOptions key={key} timeout={timeout} />;
};
const ChatWithOptions = ({ timeout }: StreamChatOptions) => {
const client = useCreateChatClient({
apiKey,
options: { timeout },
tokenOrProvider: token,
userData: { id: userId },
});
if (!client) return <div>Loading...</div>;
return <Chat client={client}></Chat>;
};Creating a Channel
By default, the Stream Chat API provides support for five different channel types of varying use cases. A channel type is required when creating a channel and dictates the available features and permissions.
The defaults include:
messaginglivestreamteamgamingcommerce
You can also create custom channel types and define your own permission sets.
To create a channel, call client.channel with:
- channel type
- channel ID (optional; auto-generated if omitted)
- channel data
const channel = client.channel("messaging", {
image: "https://cdn.com/image.png",
name: "Just Chatting",
members: ["dave-matthews", "trey-anastasio"],
// option to add custom fields
});Setting Up the Components
With a client, connected user, and channel, you can compose the core UI components.
Chat
The Chat component wraps your app and provides the ChatContext (including the StreamChat client). All other SDK components must be children of Chat.
The client instance can be accessed with our custom context hook:
import { useChatContext } from "stream-chat-react";
// ...
const { client } = useChatContext();Channel
The Channel component wraps the logic, state, and UI for a channel. It provides four contexts:
ChannelStateContext- stateful data (ex:messagesormembers)ChannelActionContext- action handlers (ex:sendMessageoropenThread)ComponentContext- custom component UI overrides (ex:AvatarorMessage)TypingContext- typing users (ex:typing)
ChannelList
The ChannelList renders a channel list and previews. If you use ChannelList, don’t pass a channel prop to Channel—ChannelList handles that internally.
Window
The Window component manages layout changes when opening or closing a Thread.
ChannelHeader
The ChannelHeader displays the active channel’s image and title.
MessageList
The MessageList renders messages and consumes the contexts provided by Channel. It accepts many optional props for customization.
MessageInput
The MessageInput component wraps the message composer UI and provides the MessageInputContext.
Thread
The Thread component renders replies for a parent message. It maintains its own state and renders a MessageList and MessageInput.
Emojis (picker & autocomplete)
The SDK supports emoji picker and autocomplete integrations. Emoji autocomplete is built on emoji-mart.
The SDK does not ship with a built-in emoji picker or emoji search index. You'll need to install and configure these yourself. See the Emoji Picker guide for setup instructions.
Read more about customization in our Theming and UI Cookbook guides.