yarn add stream-chat-react-nativeInstallation
Install the SDK in a few steps:
Best Practices
- Choose RN CLI vs Expo tabs based on your app runtime; don't mix dependencies across runtimes.
- Install only the optional features you need to keep bundle size and native setup lean.
- Add required platform permissions as you enable features (audio, camera, media library).
- Follow each dependency’s post-install steps to avoid runtime errors.
- Keep Reanimated/Worklets Babel plugin last and wrap the app in
GestureHandlerRootView.
Prerequisites
Set up the React Native development environment: React Native guide.
For Expo, follow this guide.
Add Stream Chat SDK and peer dependencies
Install the SDK:
npx expo install stream-chat-expoInstall peer dependencies:
yarn add @react-native-community/netinfo react-native-gesture-handler react-native-reanimated react-native-worklets react-native-svgnpx expo install @react-native-community/netinfo expo-image-manipulator react-native-gesture-handler react-native-reanimated react-native-svgInstalled packages:
@react-native-community/netinfofor network state.react-native-gesture-handlerfor gestures.react-native-reanimatedfor animations.react-native-workletsrequired byreact-native-reanimated.react-native-svgfor SVG support.
@react-native-community/netinfofor network state.react-native-gesture-handlerfor gestures.expo-image-manipulatorto compress images.react-native-reanimatedfor animations.react-native-svgfor SVG support.
Opt-in features
Optional features require additional dependencies.
Video playing
yarn add react-native-videonpx expo install expo-videoVoice recording and audio attachments
yarn add react-native-audio-recorder-player react-native-blob-utilFor Expo, both expo-av and expo-audio are supported.
npx expo install expo-avnpx expo install expo-audioConfiguring permissions
react-native-audio-recorder-playerfor microphone access for voice recording.
An example AndroidManifest.xml would look like this with permissions:
<uses-permission android:name="android.permission.RECORD_AUDIO" />An example Info.plist would look like this with permissions:
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your microphone for voice recording.</string>Setup varies slightly for each option:
expo-avfor microphone access for voice recording.
An example app.json config for expo would look like this to add permissions to the Info.plist on iOS, using the config plugins:
expo-audiofor microphone access for voice recording.
An example app.json config for expo would look like this to add permissions to the Info.plist on iOS, using the config plugins:
{
"expo": {
"plugins": [
// ... rest of the plugins
[
"expo-audio",
{
"microphonePermission": "$(PRODUCT_NAME) would like to use your microphone for voice recording."
}
]
]
}
}On Android (Expo), most permissions are added automatically by libraries via config plugins or package-level AndroidManifest.xml. Read more here.
expo-videofor video related configuration.
An example app.json config for expo would look like this:
{
"expo": {
"plugins": [
// ... rest of the plugins
[
"expo-video",
{
"supportsBackgroundPlayback": true,
"supportsPictureInPicture": true
}
]
]
}
}Attachment sharing
Share attachments outside the app.
yarn add react-native-blob-util react-native-sharenpx expo install expo-sharingHaptic feedback
Provide haptic feedback to the user.
yarn add react-native-haptic-feedbacknpx expo install expo-hapticsCopy message
Copy the text message content to the clipboard.
yarn add @react-native-clipboard/clipboardnpx expo install expo-clipboardShare file attachments
Share files from the device.
yarn add @react-native-documents/pickernpx expo install expo-document-pickerCapture image and upload attachment
Capture images from the camera and upload them.
yarn add react-native-image-pickernpx expo install expo-image-pickerConfiguring permissions
react-native-image-pickerfor camera access.
On Android, an example AndroidManifest.xml would look like this with permissions:
<uses-permission android:name="android.permission.CAMERA" />On iOS, an example Info.plist would look like this with permissions:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your camera to share image in a message.</string>expo-image-pickerfor camera access.
An example app.json config for expo would look like this to add permissions to the Info.plist on iOS, using the config plugins:
{
"expo": {
"plugins": [
[
"expo-image-picker",
{
"cameraPermission": "$(PRODUCT_NAME) would like to use your camera to share image in a message."
}
]
]
}
}Pick image using Native Image Picker
Pick gallery images using the native picker and upload them.
yarn add react-native-image-pickernpx expo install expo-image-pickerConfiguring permissions
react-native-image-pickerfor photo library access.
On Android, no permissions are required.
On iOS, an example Info.plist would look like this with permissions:
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo gallery to share image in a message.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME) would like to save photos to your photo gallery after downloading from a message.</string>expo-image-pickerfor camera access.
An example app.json config for expo would look like this to add permissions to the Info.plist on iOS, using the config plugins:
{
"expo": {
"plugins": [
[
"expo-image-picker",
{
"photosPermission": "$(PRODUCT_NAME) would like to use your device gallery to attach image in a message."
}
]
]
}
}Built-in image media library
Pick images using the built-in media library and upload them.
yarn add @react-native-camera-roll/camera-rollnpx expo install expo-media-libraryConfiguring permissions
@react-native-camera-roll/camera-rollfor gallery/photo library access.
An example AndroidManifest.xml would look like this with permissions:
<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" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />An example Info.plist would look like this with permissions:
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo gallery to share image in a message.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME) would like to save photos to your photo gallery after downloading from a message.</string>expo-media-libraryfor gallery/photo library access.
An example app.json config for expo would look like this to add permissions to the Info.plist on iOS, using the config plugins:
{
"expo": {
"plugins": [
[
"expo-media-library",
{
"photosPermission": "$(PRODUCT_NAME) would like access to your photo gallery to share image in a message.",
"savePhotosPermission": "$(PRODUCT_NAME) would like to save photos to your photo gallery after downloading from a message."
}
]
]
}
}On Android (Expo), most permissions are added automatically by libraries via config plugins or package-level AndroidManifest.xml. Read more here.
Offline support
Enable offline support.
yarn add @op-engineering/op-sqlitenpx expo install @op-engineering/op-sqliteHigh-performance message list
For better performance with large message lists, you can use @shopify/flash-list instead of the default FlatList. This is especially useful for channels with thousands of messages.
yarn add @shopify/flash-listnpx expo install @shopify/flash-listSee the FlashList documentation for more information on using FlashList with the SDK.
The overall installation of the optional dependencies would look like this:
@react-native-camera-roll/camera-rollfor gallery access.react-native-videofor video/audio playback.react-native-audio-recorder-playerfor audio recording.react-native-blob-utilfor file operations and cache access.react-native-sharefor sharing.react-native-haptic-feedbackfor haptics.@react-native-clipboard/clipboardfor clipboard.@react-native-documents/pickerfor file picking (required overreact-native-document-pickeron React Native>=0.78.0).react-native-image-pickerfor camera/gallery picking.@op-engineering/op-sqlitefor offline storage.
expo-avfor audio playback/recording.expo-videofor video playback/preview.expo-file-systemfor file operations and cache access.expo-media-libraryfor gallery access.expo-sharingfor sharing.expo-hapticsfor haptics.expo-clipboardfor clipboard.expo-document-pickerfor file picking.expo-image-pickerfor camera/gallery picking.@op-engineering/op-sqlitefor offline storage.
Follow each dependency's setup instructions to ensure proper integration.
Additional Steps
Some dependencies require extra app configuration:
- Add the Babel plugin for
react-native-reanimatedinbabel.config.js:
module.exports = {
presets: [
... // don't add it here :)
],
plugins: [
...
'react-native-reanimated/plugin',
],
};react-native-reanimated/plugin has to be listed last.
If you are using react-native-reanimated version >=4.0.0, you can replace the react-native-reanimated/plugin with react-native-worklets/plugin in your application's babel.config.js.
module.exports = {
presets: [
... // don't add it here :)
],
plugins: [
...
'react-native-worklets/plugin',
],
};Read more here.
- After installation, wrap your entry point with
<GestureHandlerRootView>orgestureHandlerRootHOC:
import { GestureHandlerRootView } from "react-native-gesture-handler";
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
{/* content */}
</GestureHandlerRootView>
);
}Your entry point is usually index.js or App.tsx. For Expo Router v3.x, use app/_layout.js.
Please also follow the steps mentioned in the links below for corresponding dependencies:
react-native- additional installation steps
Run the app:
npx pod-install
yarn iosyarn androidyarn run iosyarn run android