# Native Handlers

Stream Chat React Native uses native features and supports both React Native CLI and [Expo](https://expo.io/), each with different native packages.

To handle this, the SDK is split into `stream-chat-react-native-core` plus either `stream-chat-react-native` or `stream-chat-expo`. The non-core package calls `registerNativeHandlers` so the core package can use platform-specific implementations for the same tasks.

## Best Practices

- Register handlers once during app startup, not inside components.
- Mirror the SDK’s handler signatures to avoid runtime mismatches.
- Override only the handlers you need to change; keep the rest default.
- Verify Expo vs. RN CLI dependencies before swapping implementations.
- Test media flows after overriding handlers to confirm parity.

## Overriding Handlers

You can override native handlers with `registerNativeHandlers`. Use the same function the SDK uses internally, return the same types, and follow the SDK type definitions in the default implementations.

### Example

Haptic feedback is used for certain presses and in the image viewer. If you don’t want it, replace the handler.

```tsx
import { registerNativeHandlers } from "stream-chat-react-native";

registerNativeHandlers({
  triggerHaptic: () => null,
});
```

<admonition type="note">

Register handlers outside the component lifecycle to avoid re-registering.

</admonition>

## Handlers

These handlers map to different native packages depending on whether you use Expo or React Native CLI.

### `Audio`

The handler used to play audio files and for voice recording.

| React Native CLI                                                                                                                                                                        | Expo                                                                                                                           |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| [`react-native-audio-recorder-player`](https://github.com/hyochan/react-native-audio-recorder-player) & [`react-native-blob-util`](https://github.com/RonRadtke/react-native-blob-util) | [`expo-av`](https://docs.expo.dev/versions/latest/sdk/av/) or [`expo-audio`](https://docs.expo.dev/versions/latest/sdk/audio/) |

<admonition type="info">

`expo-audio` is supported from version `7.2.0` of `stream-chat-expo`.

Even though both libraries are supported and adapted to a singular API, different supported `Expo` versions do not work interoperably with each of the libraries.

More specifically, if you're using Expo `51.x.x` or `52.x.x` please make sure to keep using `expo-av` as `expo-audio` is unstable and will likely not work properly in those versions.

Conversely, if you're using Expo `>=53.0.0`, please make sure to use `expo-audio` as support for `expo-av` has stopped completely in favor of the new library. While it is already not supported, Expo `54` is not going to contain `expo-av` at all in Expo Go, meaning the sooner you get to go to Expo `53` and use the new library, the better.

</admonition>


### `overrideAudioRecordingConfiguration`

A handler to override the audio recording config used by [`Audio`](#audio). It’s a transformer: input `Audio.audioRecordingConfiguration`, return a modified config of the same type. The result is set on the `Audio` singleton.

| React Native CLI                                                                 | Expo                                                                           |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `(config: RNCLIAudioRecordingConfiguration) => RNCLIAudioRecordingConfiguration` | `(config: ExpoAudioRecordingConfiguration) => ExpoAudioRecordingConfiguration` |

Types are defined in the SDK: [RN CLI](https://github.com/GetStream/stream-chat-react-native/v8/blob/develop/package/native-package/src/optionalDependencies/Audio.ts) and [Expo](https://github.com/GetStream/stream-chat-react-native/v8/blob/develop/package/expo-package/src/optionalDependencies/Audio.ts).

RN CLI follows `react-native-audio-recorder-player` config; Expo follows `expo-av` (and `expo-audio` is compatible with that config).

### `compressImage`

Async function that compresses an image and returns the local `uri`.

| Expo                                                                                   |
| -------------------------------------------------------------------------------------- |
| [`expo-image-manipulator`](https://docs.expo.io/versions/latest/sdk/imagemanipulator/) |

### `deleteFile`

Deletes a file at a local `uri`.

| React Native CLI                                                                | Expo                                                                       |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| [`react-native-blob-util`](https://github.com/RonRadtke/react-native-blob-util) | [`expo-file-system`](https://docs.expo.io/versions/latest/sdk/filesystem/) |

### `getLocalAssetUri`

Gets the local `uri` of an image or remote asset.

| React Native CLI                                                                                              | Expo                                                                            |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`@react-native-camera-roll/camera-roll`](https://github.com/react-native-cameraroll/react-native-cameraroll) | [`expo-media-library`](https://docs.expo.io/versions/latest/sdk/media-library/) |

### `getPhotos`

Returns photos from the camera roll using `after` (offset) and `first` (count).

| React Native CLI                                                                                              | Expo                                                                            |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`@react-native-camera-roll/camera-roll`](https://github.com/react-native-cameraroll/react-native-cameraroll) | [`expo-media-library`](https://docs.expo.io/versions/latest/sdk/media-library/) |

### `pickDocument`

Opens the document picker and returns selected documents.

| React Native CLI                                                                              | Expo                                                                                |
| --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| [`@react-native-documents/picker`](https://github.com/react-native-documents/document-picker) | [`expo-document-picker`](https://docs.expo.io/versions/latest/sdk/document-picker/) |

### `pickImage`

Opens the native image picker and returns selected images.

| React Native CLI                                                                                      | Expo                                                                         |
| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| [`react-native-image-picker`](https://github.com/react-native-image-picker/react-native-image-picker) | [`expo-image-picker`](https://docs.expo.io/versions/latest/sdk/imagepicker/) |

### `saveFile`

Saves a file from a URL to local storage.

| React Native CLI                                                                | Expo                                                                       |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| [`react-native-blob-util`](https://github.com/RonRadtke/react-native-blob-util) | [`expo-file-system`](https://docs.expo.io/versions/latest/sdk/filesystem/) |

### `SDK`

String identifying which package is used: `stream-chat-react-native` or `stream-chat-expo`.

| React Native CLI           | Expo               |
| -------------------------- | ------------------ |
| _stream-chat-react-native_ | _stream-chat-expo_ |

### `setClipboardString`

Copies text to the clipboard.

| React Native CLI                                                                | Expo                                                                     |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [`react-native-clipboard`](https://github.com/react-native-clipboard/clipboard) | [`expo-clipboard`](https://docs.expo.dev/versions/latest/sdk/clipboard/) |

### `shareImage`

Shares an image using the OS share sheet.

| React Native CLI                                                                                                                                                   | Expo                                                                                                                                             |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [`react-native-blob-util`](https://github.com/RonRadtke/react-native-blob-util) & [`react-native-share`](https://github.com/react-native-share/react-native-share) | [`expo-file-system`](https://docs.expo.io/versions/latest/sdk/filesystem/) & [`expo-sharing`](https://docs.expo.io/versions/latest/sdk/sharing/) |

### `takePhoto`

Opens the OS camera to capture an image or video and returns the result.

<admonition type="note">

On iOS, the same camera instance can be used to capture image and video by switching tabs.
On Android, image and video use different camera instances. Pass `mediaType` as `image` or `video`.

</admonition>

| React Native CLI                                                                                      | Expo                                                                         |
| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| [`react-native-image-picker`](https://github.com/react-native-image-picker/react-native-image-picker) | [`expo-image-picker`](https://docs.expo.io/versions/latest/sdk/imagepicker/) |

### `triggerHaptic`

Triggers haptic feedback for a given type.

| React Native CLI                                                                            | Expo                                                                |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| [`react-native-haptic-feedback`](https://github.com/junina-de/react-native-haptic-feedback) | [`expo-haptics`](https://docs.expo.io/versions/latest/sdk/haptics/) |

### `Sound`

Renders audio attachments.

| React Native CLI                                                                 | Expo                                                                                                                           |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| [`react-native-video`](https://github.com/react-native-video/react-native-video) | [`expo-av`](https://docs.expo.dev/versions/latest/sdk/av/) or [`expo-audio`](https://docs.expo.dev/versions/latest/sdk/audio/) |

<admonition type="info">

`expo-audio` is supported from version `7.2.0` of `stream-chat-expo`.

Even though both libraries are supported and adapted to a singular API, different supported `Expo` versions do not work interoperably with each of the libraries.

More specifically, if you're using Expo `51.x.x` or `52.x.x` please make sure to keep using `expo-av` as `expo-audio` is unstable and will likely not work properly in those versions.

Conversely, if you're using Expo `>=53.0.0`, please make sure to use `expo-audio` as support for `expo-av` has stopped completely in favor of the new library. While it is already not supported, Expo `54` is not going to contain `expo-av` at all in Expo Go, meaning the sooner you get to go to Expo `53` and use the new library, the better.

</admonition>


### `Video`

Renders video in the image gallery when a video attachment is opened.

| React Native CLI                                                                 | Expo                                                             |
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [`react-native-video`](https://github.com/react-native-video/react-native-video) | [`expo-video`](https://docs.expo.dev/versions/latest/sdk/video/) |


---

This page was last updated at 2026-04-17T17:33:45.479Z.

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