# Installation

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

Install the SDK package for your toolchain, its peer dependencies, and `stream-chat`, the [JavaScript client](https://getstream.io/chat/docs/javascript/) 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

**RN CLI**

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

**Expo**

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

The 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:

**RN CLI**

```bash title="Terminal"
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/netinfo`](https://github.com/react-native-netinfo/react-native-netinfo) for the device's 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), which `react-native-reanimated` 4 needs.
- [`react-native-teleport`](https://github.com/kirillzyusko/react-native-teleport) for the overlays `OverlayProvider` hosts, such as the message menu.
- [`react-native-svg`](https://github.com/react-native-svg/react-native-svg) for icons.
- [`react-native-safe-area-context`](https://github.com/AppAndFlow/react-native-safe-area-context) for safe-area insets.

**Expo**

```bash title="Terminal"
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/netinfo`](https://github.com/react-native-netinfo/react-native-netinfo) for the device's network state.
- [`expo-image-manipulator`](https://docs.expo.dev/versions/latest/sdk/imagemanipulator/) to compress images before upload.
- [`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://docs.expo.dev/versions/latest/sdk/reanimated/), which `react-native-reanimated` 4 needs.
- [`react-native-svg`](https://docs.expo.dev/versions/latest/sdk/svg/) for icons.
- [`react-native-teleport`](https://github.com/kirillzyusko/react-native-teleport) for the overlays `OverlayProvider` hosts, such as the message menu.
- [`react-native-safe-area-context`](https://docs.expo.dev/versions/latest/sdk/safe-area-context/) for safe-area insets.

>
> **Note:** `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`:

```js title="babel.config.js"
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](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/).

Wrap the root of your app in `GestureHandlerRootView`:

```tsx title="App.tsx"
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](https://getstream.io/chat/docs/sdk/react-native/v10/getting-started/quick-start/).

## Best practices

- Install `stream-chat` next 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 declares `dayjs` too, 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

**RN CLI**

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

**Expo**

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

To configure it, for example for background playback or picture in picture, add the `expo-video` [config plugin](https://docs.expo.dev/versions/latest/sdk/video/#configuration-in-app-config) to `app.json`.

### Voice recording and audio playback

**RN CLI**

```bash title="Terminal"
yarn add react-native-nitro-sound react-native-nitro-modules react-native-blob-util
```

`react-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`:

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

On iOS, in `Info.plist`:

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

**Expo**

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

`expo-av` still works in its place, but Expo has deprecated it. Add the microphone permission through the `expo-audio` config plugin:

```json title="app.json"
{
  "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.

**RN CLI**

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

**Expo**

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

### Haptic feedback

**RN CLI**

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

**Expo**

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

### Copying messages

Copy a message's text to the clipboard from the message menu.

**RN CLI**

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

**Expo**

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

### Picking files

Attach files from the device.

**RN CLI**

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

**Expo**

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

### Taking photos and using the system image picker

Take a photo with the camera, or pick images with the system picker.

**RN CLI**

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

Add the camera permission. On Android, in `AndroidManifest.xml`:

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

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

**Expo**

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

Add the permissions through the `expo-image-picker` config plugin:

```json title="app.json"
{
  "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.

**RN CLI**

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

Add the permissions. On Android, in `AndroidManifest.xml`:

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

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

**Expo**

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

Add the permissions through the `expo-media-library` config plugin:

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

>
> **Note:** Google Play's [photo and video permissions policy](https://support.google.com/googleplay/android-developer/answer/14115180) 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.

**RN CLI**

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

**Expo**

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

Expo Go can't load it, so use a [development build](https://docs.expo.dev/develop/development-builds/introduction/).

Then set `enableOfflineSupport` on `Chat`. See [Offline support](https://getstream.io/chat/docs/sdk/react-native/v10/state/offline-support/offline-support/).

### FlashList message list

`MessageFlashList` renders the message list with [`@shopify/flash-list`](https://shopify.github.io/flash-list/) 2.1 or later, in place of `MessageList`, which uses `FlatList`.

**RN CLI**

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

**Expo**

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

## Entry 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](https://getstream.io/chat/docs/sdk/react-native/v10/features/ai/ai-integrations-overview/).

---

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