Installation
Install the SDK package for your toolchain, its peer dependencies, and stream-chat, the JavaScript client that holds the state. stream-chat-react-native and stream-chat-expo 10 and stream-chat 10 are release candidates, published under the rc tag. The SDK needs stream-chat 10.0.0-rc.26 or later.
The SDK needs React Native 0.79 or later with the New Architecture, and for Expo apps, Expo SDK 53 or later. stream-chat 10 needs Node 22.18 or later to install.
Install the SDK
yarn add stream-chat-react-native@rc stream-chat@rcnpx expo install stream-chat-expo@rc stream-chat@rcThe SDK depends on stream-chat itself. Your app imports from it too, for example ChannelPaginator and the types, so add it to your app at the version the SDK uses. Exactly one copy must resolve: a second copy makes the client and the objects your app creates come from different classes.
Then install the peer dependencies:
yarn add @react-native-community/netinfo react-native-gesture-handler react-native-reanimated react-native-worklets react-native-teleport react-native-svg react-native-safe-area-context@react-native-community/netinfofor the device's network state.react-native-gesture-handlerfor gestures.react-native-reanimatedfor animations.react-native-worklets, whichreact-native-reanimated4 needs.react-native-teleportfor the overlaysOverlayProviderhosts, such as the message menu.react-native-svgfor icons.react-native-safe-area-contextfor safe-area insets.
npx expo install @react-native-community/netinfo expo-image-manipulator react-native-gesture-handler react-native-reanimated react-native-worklets react-native-svg react-native-teleport react-native-safe-area-context@react-native-community/netinfofor the device's network state.expo-image-manipulatorto compress images before upload.react-native-gesture-handlerfor gestures.react-native-reanimatedfor animations.react-native-worklets, whichreact-native-reanimated4 needs.react-native-svgfor icons.react-native-teleportfor the overlaysOverlayProviderhosts, such as the message menu.react-native-safe-area-contextfor safe-area insets.
react-native-teleport and several optional packages below are native modules. After adding one, rebuild the app: run npx pod-install for React Native CLI, or npx expo prebuild for an Expo app that uses prebuild.
Configure the app
Add the Babel plugin of react-native-reanimated to babel.config.js, as the last plugin. With react-native-reanimated 4, the plugin is react-native-worklets/plugin:
module.exports = {
presets: [
// your presets
],
plugins: [
// your other plugins
"react-native-worklets/plugin",
],
};With react-native-reanimated 3, use react-native-reanimated/plugin instead. See the Reanimated installation guide.
Wrap the root of your app in GestureHandlerRootView:
import { GestureHandlerRootView } from "react-native-gesture-handler";
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
{/* the rest of the app */}
</GestureHandlerRootView>
);
}For Expo Router, the root is app/_layout.tsx.
To build a first app, continue with the Quick start.
Best practices
- Install
stream-chatnext to the SDK and upgrade them together. The SDK depends on newer client features, so mismatched versions can fail at runtime even if installation succeeds. - Use the package that matches your toolchain, and never install both.
- Install only the optional features you need. Each one adds a native module.
- Add the platform permissions a feature needs (microphone, camera, photo library) when you add it.
- Keep a single copy of
dayjs(the SDK uses^1.11.23). If your app declaresdayjstoo, use a compatible range.
Optional features
Each feature below turns on when its package is installed. Without the package, the SDK leaves the feature out.
Video playback
yarn add react-native-videonpx expo install expo-videoTo configure it, for example for background playback or picture in picture, add the expo-video config plugin to app.json.
Voice recording and audio playback
yarn add react-native-nitro-sound react-native-nitro-modules react-native-blob-utilreact-native-nitro-sound records and plays audio. react-native-audio-recorder-player still works in its place, but it's deprecated. react-native-blob-util reads and writes the recorded files.
Add the microphone permission. On Android, in AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" />On iOS, in Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your microphone for voice recording.</string>npx expo install expo-audioexpo-av still works in its place, but Expo has deprecated it. Add the microphone permission through the expo-audio config plugin:
{
"expo": {
"plugins": [
[
"expo-audio",
{
"microphonePermission": "$(PRODUCT_NAME) would like to use your microphone for voice recording."
}
]
]
}
}Voice recording is off until you turn it on with the audioRecordingEnabled prop of Channel and Thread.
Sharing attachments
Share an attachment to another app.
yarn add react-native-blob-util react-native-sharenpx expo install expo-sharing expo-file-systemHaptic feedback
yarn add react-native-haptic-feedbacknpx expo install expo-hapticsCopying messages
Copy a message's text to the clipboard from the message menu.
yarn add @react-native-clipboard/clipboardnpx expo install expo-clipboardPicking files
Attach files from the device.
yarn add @react-native-documents/pickernpx expo install expo-document-pickerTaking photos and using the system image picker
Take a photo with the camera, or pick images with the system picker.
yarn add react-native-image-pickerAdd the camera permission. On Android, in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />On iOS, in Info.plist, add the camera permission, and the photo library permission for the system picker:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your camera to share an image in a message.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo library to share an image in a message.</string>npx expo install expo-image-pickerAdd the permissions through the expo-image-picker config plugin:
{
"expo": {
"plugins": [
[
"expo-image-picker",
{
"cameraPermission": "$(PRODUCT_NAME) would like to use your camera to share an image in a message.",
"photosPermission": "$(PRODUCT_NAME) would like access to your photo library to share an image in a message."
}
]
]
}
}Built-in media library
Pick photos and videos from the attachment picker's own grid instead of the system picker.
yarn add @react-native-camera-roll/camera-rollAdd the permissions. On Android, in AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />The SDK asks for READ_MEDIA_IMAGES and READ_MEDIA_VIDEO on Android 13 and later, and for READ_EXTERNAL_STORAGE on earlier versions. It only reads the library, so it doesn't need WRITE_EXTERNAL_STORAGE.
On iOS, in Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo library to share an image in a message.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME) would like to save photos to your photo library after downloading them from a message.</string>npx expo install expo-media-libraryAdd the permissions through the expo-media-library config plugin:
{
"expo": {
"plugins": [
[
"expo-media-library",
{
"photosPermission": "$(PRODUCT_NAME) would like access to your photo library to share an image in a message.",
"savePhotosPermission": "$(PRODUCT_NAME) would like to save photos to your photo library after downloading them from a message."
}
]
]
}
}On Android, the config plugin and the package's own manifest add the storage and media permissions, so you add none yourself. See Permissions in the Expo docs.
Google Play's photo and video permissions policy allows READ_MEDIA_IMAGES and READ_MEDIA_VIDEO only for apps that need broad access to the user's photos and videos. An app that doesn't qualify leaves the built-in media library out. It doesn't install @react-native-camera-roll/camera-roll or expo-media-library, and doesn't declare those permissions. In an Expo app, list them under android.blockedPermissions in app.json, which also removes them when another package adds them. With react-native-image-picker or expo-image-picker installed, the attachment picker's photo button then opens the system picker, which needs no Android permission.
Offline support
Keep channels and messages in a local SQLite database, so the app shows them before it connects and queues what the user does while offline.
yarn add @op-engineering/op-sqlitenpx expo install @op-engineering/op-sqliteExpo Go can't load it, so use a development build.
Then set enableOfflineSupport on Chat. See Offline support.
FlashList message list
MessageFlashList renders the message list with @shopify/flash-list 2.1 or later, in place of MessageList, which uses FlatList.
yarn add @shopify/flash-listnpx expo install @shopify/flash-listEntry points
Each package has two entry points:
| Part | RN CLI | Expo |
|---|---|---|
| Components, contexts and hooks | stream-chat-react-native |
stream-chat-expo |
| AI components: streaming messages, Markdown, the AI composer | stream-chat-react-native/ai-components |
stream-chat-expo/ai-components |
Metro doesn't drop unused code, so the AI components are kept out of the main entry point: an app that never imports ai-components doesn't bundle them. It imports @shopify/react-native-skia and victory-native for its charts, so an app that imports ai-components installs both, and its dictation is compiled into the iOS app only when you turn it on. See AI integrations.