# React Native SDK 3.0 to 3.1

> What changes when you move the Grovs React Native wrapper from 3.0.x to 3.1.0, which wraps iOS SDK 3.1 and Android SDK 3.1.0.

Source: https://docs.grovs.io/docs/upgrade-guides/react-native-3-1

`react-native-grovs-wrapper` 3.1.0 moves to iOS SDK 3.1 and Android SDK 3.1.0. It adds [push campaigns](https://docs.grovs.io/docs/sdk/react-native/push-notifications), [in-app messages](https://docs.grovs.io/docs/sdk/react-native/in-app-messages) and [`linkDetails`](https://docs.grovs.io/docs/sdk/react-native/link-creation#inspecting-a-link), and removes the messages inbox. Most apps bump the packages, run `pod install` and fix what TypeScript flags.

Requirements are unchanged: React Native 0.70 or later, iOS 13.0, Android 5.0 (API 21).

## Checklist

1. [Bump the packages](#1-bump-the-packages): the wrapper, `io.grovs:Grovs` in your app's `build.gradle`, and the iOS pods.
2. [Handle an optional `DeeplinkResponse.link`](#2-handle-an-optional-link).
3. [Remove native in-app delegates and listeners](#3-remove-native-in-app-delegates-and-listeners) you set yourself.
4. [Remove the messages inbox](#4-remove-the-messages-inbox) from your UI.
5. [Rename custom events that use a reserved name](#5-rename-reserved-event-names).
6. [Check the other behavior changes](#6-other-behavior-changes).
7. Optional: [set up push campaigns](https://docs.grovs.io/docs/sdk/react-native/push-notifications) and [react to in-app messages](https://docs.grovs.io/docs/sdk/react-native/in-app-messages).

## 1. Bump the packages

```bash
npm install react-native-grovs-wrapper@latest
```

In `android/app/build.gradle`:

```groovy
implementation 'io.grovs:Grovs:3.1.0'
```

The podspec now depends on `Grovs ~> 3.1`. Run `pod install` in `ios/`. If CocoaPods keeps the locked 3.0 version, run `pod update Grovs`.

**Expo:** the plugin writes the new Android dependency for you. Run `npx expo prebuild --clean`, so the `configure` calls are regenerated too (the plugin skips files that already contain `Grovs.configure`). Save manual native edits first.

## 2. Handle an optional link

`DeeplinkResponse.link` is now `link?: string`. A tapped push campaign without a link arrives with `data` only. TypeScript flags code that uses `link` as a `string`:

```typescript
Grovs.onDeeplinkReceived((response) => {
    if (response.link) {
        analytics.log('opened_link', response.link);
    }
    // route on response.data as before
});
```

## 3. Remove native in-app delegates and listeners

The wrapper sets `Grovs.inAppDelegate` on iOS and `Grovs.setInAppListener` on Android, and forwards their callbacks to [`onInAppMessage`](https://docs.grovs.io/docs/sdk/react-native/api-reference#oninappmessage). Remove any you set in native code; otherwise `onInAppMessage` gets no events.

On iOS, keep the `configure` delegate as `GrovsWrapperSwift.shared` (what the Expo plugin injects) or `nil`. Don't pass your own `GrovsDelegate`.

## 4. Remove the messages inbox

The inbox is gone from the backend and the native 3.1 SDKs. In-app messages replace it.

- `displayMessages()` is deprecated, shows nothing and resolves.
- `numberOfUnreadMessages()` is deprecated and always resolves `0`.
- Both still reject with `'SDK_DISABLED'` while the SDK is disabled.

Remove inbox buttons and unread badges.

## 5. Rename reserved event names

`track` now refuses the in-app, push and journey event names. Rename any custom event that uses one:

`in_app_viewed`, `in_app_clicked`, `in_app_dismissed`, `in_app_answered`, `in_app_commented`, `in_app_held`, `push_open`, `push_delivered`, `push_held`, `journey_entered`, `journey_held`, `journey_path`.

A refused event is logged natively and dropped; `track` doesn't throw.

## 6. Other behavior changes

- **In-app messages show on their own.** Live in-app campaigns in your project start showing after the upgrade, with no code. Use [pause and excluded screens](https://docs.grovs.io/docs/sdk/react-native/in-app-messages#hold-messages-back) for flows where they shouldn't appear.
- **Error codes.** `logInAppPurchase` and `logCustomPurchase` rejections now keep the native `code`, like the other promise methods.
- **Desktop redirect on Android.** `generateLink` now forwards the `desktop` entry's own `open_if_app_installed`. Before, Android sent the `ios` flag (new architecture) or `true` (legacy bridge).
- **Push token on Android.** When Firebase Messaging is in the app, the wrapper fetches the FCM token itself when its native module starts.

## Verify the upgrade

1. Build both platforms and fix any TypeScript errors on `response.link`.
2. Open a Grovs link and check that `onDeeplinkReceived` still receives it.
3. Call `Grovs.setIdentifier` with your own ID. In the dashboard, create an in-app campaign triggered on app open, use **Send test**, and bring the app to the foreground. The message shows at the next sync, and `onInAppMessage` gets a `shown` event.
4. If you use push, send a campaign to your own user and tap it. `onDeeplinkReceived` gets the push, and the open shows in the campaign report.

Native changes: [iOS 3.1 upgrade guide](https://docs.grovs.io/docs/upgrade-guides/ios-3-1).
