# Installation

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](https://reactnative.dev/docs/environment-setup).

For Expo, follow [this guide](https://docs.expo.dev/get-started/installation/).

## Add Stream Chat SDK and peer dependencies

Install the SDK:

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add stream-chat-react-native
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install stream-chat-expo
```

</tabs-item>

</tabs>

Install peer dependencies:

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @react-native-community/netinfo react-native-gesture-handler react-native-reanimated react-native-worklets react-native-svg
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install @react-native-community/netinfo expo-image-manipulator react-native-gesture-handler react-native-reanimated react-native-svg
```

</tabs-item>

</tabs>

Installed packages:

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`@react-native-community/netinfo`](https://github.com/react-native-netinfo/react-native-netinfo) for network state.
- [`react-native-gesture-handler`](https://github.com/software-mansion/react-native-gesture-handler) for gestures.
- [`react-native-reanimated`](https://github.com/software-mansion/react-native-reanimated) for animations.
- [`react-native-worklets`](https://github.com/software-mansion/react-native-reanimated/tree/main/packages/react-native-worklets) required by `react-native-reanimated`.
- [`react-native-svg`](https://github.com/react-native-svg/react-native-svg) for SVG support.

</tabs-item>

<tabs-item value="expo" label="Expo">

- [`@react-native-community/netinfo`](https://github.com/react-native-netinfo/react-native-netinfo) for network state.
- [`react-native-gesture-handler`](https://github.com/software-mansion/react-native-gesture-handler) for gestures.
- [`expo-image-manipulator`](https://docs.expo.dev/versions/latest/sdk/imagemanipulator/) to compress images.
- [`react-native-reanimated`](https://github.com/software-mansion/react-native-reanimated) for animations.
- [`react-native-svg`](https://docs.expo.dev/versions/latest/sdk/svg/) for SVG support.

</tabs-item>

</tabs>

## Opt-in features

Optional features require additional dependencies.

### Video playing

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-video
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-video
```

</tabs-item>

</tabs>

### Voice recording and audio attachments

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-audio-recorder-player react-native-blob-util
```

</tabs-item>

<tabs-item value="expo" label="Expo">

For Expo, both `expo-av` and `expo-audio` are supported.

<tabs>

<tabs-item value="expoav" label="expo-av">

```bash title="Terminal"
npx expo install expo-av
```

</tabs-item>

<tabs-item value="expoaudio" label="expo-audio">

```bash title="Terminal"
npx expo install expo-audio
```

</tabs-item>

</tabs>

<partial id="chat-sdk/react-native/v7-latest/_partials/common-content/admonitions/expo-audio-compatibility"></partial>

</tabs-item>

</tabs>

#### Configuring permissions

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`react-native-audio-recorder-player`](https://github.com/hyochan/react-native-audio-recorder-player?tab=readme-ov-file#post-installation) for microphone access for voice recording.

An example `AndroidManifest.xml` would look like this with permissions:

```xml
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
```

An example `Info.plist` would look like this with permissions:

```xml
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your microphone for voice recording.</string>
```

</tabs-item>

<tabs-item value="expo" label="Expo">

Setup varies slightly for each option:

<tabs>

<tabs-item value="expoav" label="expo-av">

- [`expo-av`](https://docs.expo.dev/versions/latest/sdk/av/#configuration-in-app-config) for 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:

</tabs-item>

<tabs-item value="expoaudio" label="expo-audio">

- [`expo-audio`](https://docs.expo.dev/versions/latest/sdk/audio/#configuration-in-app-config) for 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:

```json
{
  "expo": {
    "plugins": [
      // ... rest of the plugins
      [
        "expo-audio",
        {
          "microphonePermission": "$(PRODUCT_NAME) would like to use your microphone for voice recording."
        }
      ]
    ]
  }
}
```

</tabs-item>

</tabs>

On Android (Expo), most permissions are added automatically by libraries via config plugins or package-level `AndroidManifest.xml`. Read more [here](https://docs.expo.dev/guides/permissions/#android).

- [`expo-video`](https://docs.expo.dev/versions/latest/sdk/video/#configuration-in-app-config) for video related configuration.

An example `app.json` config for expo would look like this:

```json
{
  "expo": {
    "plugins": [
      // ... rest of the plugins
      [
        "expo-video",
        {
          "supportsBackgroundPlayback": true,
          "supportsPictureInPicture": true
        }
      ]
    ]
  }
}
```

</tabs-item>

</tabs>

### Attachment sharing

Share attachments outside the app.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-blob-util react-native-share
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-sharing
```

</tabs-item>

</tabs>

### Haptic feedback

Provide haptic feedback to the user.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-haptic-feedback
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-haptics
```

</tabs-item>

</tabs>

### Copy message

Copy the text message content to the clipboard.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @react-native-clipboard/clipboard
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-clipboard
```

</tabs-item>

</tabs>

### Share file attachments

Share files from the device.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @react-native-documents/picker
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-document-picker
```

</tabs-item>

</tabs>

### Capture image and upload attachment

Capture images from the camera and upload them.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-image-picker
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-image-picker
```

</tabs-item>

</tabs>

#### Configuring permissions

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`react-native-image-picker`](https://github.com/react-native-image-picker/react-native-image-picker?tab=readme-ov-file#post-install-steps) for camera access.

On Android, an example `AndroidManifest.xml` would look like this with permissions:

```xml
  <uses-permission android:name="android.permission.CAMERA" />
```

On iOS, an example `Info.plist` would look like this with permissions:

```xml
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your camera to share image in a message.</string>
```

</tabs-item>

<tabs-item value="expo" label="Expo">

- [`expo-image-picker`](https://docs.expo.dev/versions/latest/sdk/imagepicker/#configuration-in-appjsonappconfigjs) for 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:

```json
{
  "expo": {
    "plugins": [
      [
        "expo-image-picker",
        {
          "cameraPermission": "$(PRODUCT_NAME) would like to use your camera to share image in a message."
        }
      ]
    ]
  }
}
```

</tabs-item>

</tabs>

### Pick image using Native Image Picker

Pick gallery images using the native picker and upload them.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add react-native-image-picker
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-image-picker
```

</tabs-item>

</tabs>

#### Configuring permissions

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`react-native-image-picker`](https://github.com/react-native-image-picker/react-native-image-picker?tab=readme-ov-file#post-install-steps) for photo library access.

On Android, no permissions are required.

On iOS, an example `Info.plist` would look like this with permissions:

```xml
<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>
```

</tabs-item>

<tabs-item value="expo" label="Expo">

- [`expo-image-picker`](https://docs.expo.dev/versions/latest/sdk/imagepicker/#configuration-in-appjsonappconfigjs) for 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:

```json
{
  "expo": {
    "plugins": [
      [
        "expo-image-picker",
        {
          "photosPermission": "$(PRODUCT_NAME) would like to use your device gallery to attach image in a message."
        }
      ]
    ]
  }
}
```

</tabs-item>

</tabs>

### Built-in image media library

Pick images using the built-in media library and upload them.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @react-native-camera-roll/camera-roll
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install expo-media-library
```

</tabs-item>

</tabs>

#### Configuring permissions

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`@react-native-camera-roll/camera-roll`](https://github.com/react-native-cameraroll/react-native-cameraroll?tab=readme-ov-file#permissions) for gallery/photo library access.

An example `AndroidManifest.xml` would look like this with permissions:

```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" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```

An example `Info.plist` would look like this with permissions:

```xml
<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>
```

</tabs-item>

<tabs-item value="expo" label="Expo">

- [`expo-media-library`](https://docs.expo.dev/versions/latest/sdk/media-library/#configurable-properties) for 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:

```json
{
  "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](https://docs.expo.dev/guides/permissions/#android).

</tabs-item>

</tabs>

### Offline support

Enable offline support.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @op-engineering/op-sqlite
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install @op-engineering/op-sqlite
```

</tabs-item>

</tabs>

### High-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.

<tabs>

<tabs-item value="rncli" label="RN CLI">

```bash title="Terminal"
yarn add @shopify/flash-list
```

</tabs-item>

<tabs-item value="expo" label="Expo">

```bash title="Terminal"
npx expo install @shopify/flash-list
```

</tabs-item>

</tabs>

<admonition type="note">

See the [FlashList documentation](/chat/docs/sdk/react-native/ui-components/experimental/message-flash-list/) for more information on using FlashList with the SDK.

</admonition>

The overall installation of the optional dependencies would look like this:

<tabs>

<tabs-item value="rncli" label="RN CLI">

- [`@react-native-camera-roll/camera-roll`](https://github.com/react-native-cameraroll/react-native-cameraroll) for gallery access.
- [`react-native-video`](https://github.com/react-native-video/react-native-video) for video/audio playback.
- [`react-native-audio-recorder-player`](https://github.com/hyochan/react-native-audio-recorder-player) for audio recording.
- [`react-native-blob-util`](https://github.com/RonRadtke/react-native-blob-util) for file operations and cache access.
- [`react-native-share`](https://github.com/react-native-share/react-native-share) for sharing.
- [`react-native-haptic-feedback`](https://github.com/junina-de/react-native-haptic-feedback) for haptics.
- [`@react-native-clipboard/clipboard`](https://github.com/react-native-clipboard/clipboard) for clipboard.
- [`@react-native-documents/picker`](https://github.com/react-native-documents/document-picker) for file picking (required over `react-native-document-picker` on React Native `>=0.78.0`).
- [`react-native-image-picker`](https://github.com/react-native-image-picker/react-native-image-picker) for camera/gallery picking.
- [`@op-engineering/op-sqlite`](https://github.com/OP-Engineering/op-sqlite) for offline storage.

</tabs-item>

<tabs-item value="expo" label="Expo">

- [`expo-av`](https://docs.expo.dev/versions/latest/sdk/av/) for audio playback/recording.
- [`expo-video`](https://docs.expo.dev/versions/latest/sdk/video/) for video playback/preview.
- [`expo-file-system`](https://docs.expo.dev/versions/latest/sdk/filesystem/) for file operations and cache access.
- [`expo-media-library`](https://docs.expo.dev/versions/latest/sdk/media-library/) for gallery access.
- [`expo-sharing`](https://docs.expo.dev/versions/latest/sdk/sharing/) for sharing.
- [`expo-haptics`](https://docs.expo.dev/versions/latest/sdk/haptics/) for haptics.
- [`expo-clipboard`](https://docs.expo.dev/versions/latest/sdk/clipboard/) for clipboard.
- [`expo-document-picker`](https://docs.expo.dev/versions/latest/sdk/document-picker/) for file picking.
- [`expo-image-picker`](https://docs.expo.dev/versions/latest/sdk/imagepicker/) for camera/gallery picking.
- [`@op-engineering/op-sqlite`](https://github.com/OP-Engineering/op-sqlite) for offline storage.

</tabs-item>

</tabs>

<admonition type="note">

Follow each dependency's setup instructions to ensure proper integration.

</admonition>

## Additional Steps

Some dependencies require extra app configuration:

- Add the Babel plugin for [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation#babel-plugin) in `babel.config.js`:

```js {7}
module.exports = {
  presets: [
    ... // don't add it here :)
  ],
  plugins: [
    ...
    'react-native-reanimated/plugin',
  ],
};
```

<admonition type="warning">

`react-native-reanimated/plugin` has to be listed last.

</admonition>

<admonition type="note">

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`.

```js {7}
module.exports = {
  presets: [
    ... // don't add it here :)
  ],
  plugins: [
    ...
    'react-native-worklets/plugin',
  ],
};
```

Read more [here](https://docs.swmansion.com/react-native-reanimated/docs/guides/migration-from-3.x#renamed-react-native-reanimatedplugin).

</admonition>

- After installation, wrap your entry point with `<GestureHandlerRootView>` or `gestureHandlerRootHOC`:

```js
import { GestureHandlerRootView } from "react-native-gesture-handler";

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* content */}
    </GestureHandlerRootView>
  );
}
```

<admonition type="note">

Your entry point is usually `index.js` or `App.tsx`. For Expo Router v3.x, use `app/_layout.js`.

</admonition>

Please also follow the steps mentioned in the links below for corresponding dependencies:

- `react-native` - [additional installation steps](https://reactnative.dev/docs/image#gif-and-webp-support-on-android)

Run the app:

<tabs>

<tabs-item value="rncli" label="RN CLI">

<tabs>

<tabs-item value="iOS" label="iOS">

```bash title="Terminal"
npx pod-install
yarn ios
```

</tabs-item>

<tabs-item value="android" label="Android">

```bash title="Terminal"
yarn android
```

</tabs-item>

</tabs>

</tabs-item>

<tabs-item value="expo">

<tabs>

<tabs-item value="iOS" label="iOS">

```bash title="Terminal"
yarn run ios
```

</tabs-item>

<tabs-item value="android" label="Android">

```bash title="Terminal"
yarn run android
```

</tabs-item>

</tabs>

</tabs-item>

</tabs>


---

This page was last updated at 2026-03-06T17:06:05.625Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/basics/installation/](https://getstream.io/chat/docs/sdk/react-native/basics/installation/).