Overview
Stream Chat React Native is an SDK for chat on the Stream Chat API in React Native CLI and Expo apps: team and social messaging, livestream chat, customer support and similar apps.
It has two layers:
- State lives in
stream-chat, the JavaScript client. Channels, threads, message lists and composers are objects that keep their data in reactive stores. You configure them throughclient.config. - UI lives in
stream-chat-react-native-core, which ships to apps asstream-chat-react-nativefor React Native CLI andstream-chat-expofor Expo. Its components read those stores and re-render when they change. You replace any of them throughWithComponents.
Navigation is up to your app. The SDK renders a channel list, a channel and a thread, and tells you when the user picks a channel or opens a thread. Your navigator, such as React Navigation or Expo Router, decides which screen shows them.
To see the two layers work together, read How the SDK is built. It follows one message from the composer to the message list.
The SDK components cover:
- Channel lists, message lists and the message composer
- Threads, the thread list and quoted replies
- Reactions, mentions and slash commands
- Image, video and file attachments, with uploads and an image gallery
- Voice recordings and audio playback
- Polls and location sharing
- Read state, unread counts and typing indicators
- Search across channels, messages and users
- Offline storage with SQLite
Start here
Build a working chat app from an empty project.
Install the SDK and render your first chat screens.
Follow one message through the state and UI layers.
The stream-chat client API for connections, channels and messages.
Build with Stream CLI and Agent Skills
The Stream CLI and Agent Skills provide AI coding agents, such as Claude Code, Cursor, and Codex, with the tools and knowledge necessary to build apps with Stream.
Install the CLI and add the skills to your project:
curl -fsSL https://getstream.io/cli.sh | bash
getstream skills stream-react-nativeOnce installed, invoke it from your agent:
/stream Add Stream Chat to my React Native app.The /stream skill acts as a router, reading your request and dispatching it to the specialist skill. You can also invoke the /stream-react-native skill directly.
Stream Agent Skills can also be installed from skills.sh.
Best practices
- Start with the SDK's components and replace only the parts that need a different design.
- Use built-in features (threads, reactions, uploads, indicators) before building your own.
- Change behavior through
client.config, and appearance throughWithComponentsand the theme. Both stay in place when you update the SDK. - Install the package that matches your toolchain,
stream-chat-react-nativeorstream-chat-expo, and never both.
What's new in v10
v10 is an architectural release. The UI is largely unchanged. What moved is where state lives, how a channel list and a thread get on screen, and how the SDK is configured.
State lives in the low-level client
Messages, channel lists, threads, search and the composer are owned by stream-chat objects, each holding a StateStore. Components subscribe to the part they render with useStateStore, so there is one source for any value and no copy kept in React.
For example, this badge shows the number of unread threads and updates when it changes:
import { Text } from "react-native";
import type { ThreadManagerState } from "stream-chat";
import { useChatContext, useStateStore } from "stream-chat-react-native";
// Declared outside the component, so the subscription isn't recreated on every render.
const selector = (state: ThreadManagerState) => ({
unreadThreadCount: state.unreadThreadCount,
});
export const UnreadThreadsBadge = () => {
const { client } = useChatContext();
const { unreadThreadCount } = useStateStore(client.threads.state, selector);
return <Text>{unreadThreadCount} unread threads</Text>;
};TypingContext and PaginatedMessageListContext are gone with it, and so are most of the values ChannelContext, ThreadContext and ChannelsContext used to hold. State is read from the instance, and actions are called on it. See Reactive state and Reading state in components.
Pagination is a shared model
One BasePaginator backs channel lists, message history, thread replies, reminders and user groups, with cursors, ordering and loading state in one place. A ChannelList renders a ChannelPaginator that your app creates and registers on client.channelManager, which keeps every registered paginator in sync from a single set of WebSocket subscriptions, so several lists can coexist. The list's filters, sort and query options are set on the paginator, not on ChannelList. See Channel list paginators.
Threads render on their own
Thread is a component of its own, rendered next to Channel rather than inside it, and it takes a Thread instance from stream-chat. Your app keeps the open thread, for example in a navigation route, and renders <Thread thread={thread}> with a message list and a composer as its children. Channel and Thread each activate their channel or thread, with Channel.activate() or Thread.activate(), so the client knows which ones are on screen: it keeps them loaded and reloads them after a reconnect. See Entity lifecycle.
One place to configure instances
client.config is a configuration registry for the objects the SDK builds: channels, threads, composers, paginators and the client's own managers. It replaces the request-handler and throttling props that Channel used to take, and it is where a setup function goes when configuration values cannot express the customization. See Configuration.
Localization by stable keys
Translation keys are namespaced identifiers rather than English sentences, with the copy inline at each call site. English is the only bundled language, and a partial custom dictionary is safe because an unsupplied key still renders.
Upgrading from v9 is covered in the v10 upgrade guide.
Architecture
The two layers are two packages, and they meet in stores.
State: stream-chat. The client creates one Channel object per channel and one Thread object per thread. Each keeps its data in stores. For a channel, channel.state holds the members, read state and typing users, channel.messagePaginator holds the loaded messages, and channel.messageComposer holds what the user is writing. WebSocket events update these stores. You configure these objects through client.config. None of this depends on React.
UI: stream-chat-react-native. A component subscribes to the part of a store it shows, with useStateStore, and re-renders when that part changes. Chat gives every component below it the client, read with useChatContext(). Channel gives its children a channel and Thread a thread, read with useChannel() and useThreadContext(). OverlayProvider, above Chat, hosts the parts that draw over the whole screen: the message menu and the image gallery. You replace any component through WithComponents.
For example, when a new message arrives, channel.messagePaginator adds it to its store. MessageList subscribes to that store, so it re-renders with the new message. React keeps no copy of the messages.
The SDK ships as two packages, one per toolchain. Both re-export everything from stream-chat-react-native-core and register the native modules for their toolchain:
stream-chat-react-nativefor React Native CLI apps.stream-chat-expofor Expo apps.
The AI components (streaming messages, Markdown, the AI composer) are a separate entry point of each package, stream-chat-react-native/ai-components and stream-chat-expo/ai-components, so an app that doesn't import them doesn't bundle them.
Supported platforms
The SDK runs on iOS and Android. It needs React Native 0.79 or later with the New Architecture, and for Expo apps, Expo SDK 53 or later. Web isn't supported; use the React SDK for web apps.
Upgrading and versioning
The SDK follows semantic versioning:
- Bug fixes and behavior improvements bump the patch version.
- New features bump the minor version.
- Incompatible API changes bump the major version.
Minor versions can include visual changes (spacing, colors, sizing) as the default UI evolves. Pin an exact version if you need visual stability.
Sample apps
Sample apps live in the examples directory of the SDK repository: SampleApp for React Native CLI, ExpoMessaging for Expo, and ExpoChatGPTSample for the AI components.
What's next
Add stream-chat-react-native or stream-chat-expo to your app.
How the stores hold state and notify subscribers.
Move an app from v9 to v10.
FAQ
How do I upgrade from v9?
Follow the v10 upgrade guide.
How do I enable offline support?
It's opt-in: install @op-engineering/op-sqlite and set enableOfflineSupport on Chat. See Offline support. Expo Go can't run it; use a development build.
Does chat include moderation?
Yes. AI engines screen messages and users can flag content into a dashboard review queue. See moderation for chat.