# React Native SDK

`@rollbird/react-native` connects a shipped React Native binary to Rollbird's
OTA service. The only required runtime option is the public `projectKey`
written by `rollbird init`.

> **Availability:** [`@rollbird/react-native`](https://www.npmjs.com/package/@rollbird/react-native)
> is available from the public npm registry.

## Compatibility

| Dependency | Supported contract |
| --- | --- |
| Node.js | 20 or newer for the CLI and build tooling |
| React Native | 0.76 is the verified baseline; the package currently declares `react-native: "*"` |
| Expo | Expo 50 or newer, with `@expo/config-plugins` 9 or newer |
| iOS | Deployment target 13.4 or newer through the pinned native client |
| Android | Uses the app's existing minimum and compile SDK versions |
| Hot Updater | `@hot-updater/react-native` 0.36.13 is pinned internally |

Rollbird uses the JavaScript engine selected by the app. When Hermes is
enabled, the CLI resolves the Hermes compiler from that app's own React Native
installation so the bytecode matches the installed native runtime.

## Install and configure

Run the setup command from the app root:

```bash
npx rollbird init --channel preview
```

It installs the SDK dependencies, links or creates the Rollbird project,
provisions signing, writes `rollbird.json`, and configures the native targets
or Expo plugin. See [Getting started](/docs/getting-started/) for the complete
first-release walkthrough.

Then wrap the root component:

```tsx
import { Rollbird } from "@rollbird/react-native";

export default Rollbird.wrap({ projectKey: "pk_from_rollbird_json" })(App);
```

The project key is public app configuration. Never put `ROLLBIRD_TOKEN` or a
private signing key in application code.

## Wrapper options

| Option | Type | Behavior |
| --- | --- | --- |
| `projectKey` | `string` | Required public key from `rollbird.json`. |
| `apiUrl` | `string` | Overrides `https://ota.rollbird.dev`; intended for local development. |
| `strategy` | `"fingerprint" \| "appVersion"` | Compatibility strategy. Defaults to `fingerprint`. |
| `fallbackComponent` | React component | Receives `{ progress, status }` while the update process blocks rendering. |
| `onProgress` | callback | Receives `{ progress }`, where progress is the native client's numeric value. |
| `onUpdateProcessCompleted` | callback | Receives the native client's completion result. |
| `onNotifyAppReady` | callback | Receives the native client's app-ready result, including recovery state. |
| `onError` | callback | Receives an `Error` when the update process fails. |
| `reloadOnForceUpdate` | `boolean` | Controls automatic reload for forced updates; the native client defaults it to on. |
| `requestTimeout` | `number` | Overrides the update-request timeout. |
| `requestHeaders` | `Record<string, string>` | Adds headers to update requests. Do not use it for secrets embedded in the app. |

Example with progress and error reporting:

```tsx
export default Rollbird.wrap({
  projectKey: "pk_from_rollbird_json",
  onProgress: ({ progress }) => console.log("Rollbird download", progress),
  onError: (error) => console.warn("Rollbird update failed", error),
})(App);
```

The client also exposes `checkForUpdate`, `runUpdateProcess`, `getBundleId`,
`getChannel`, `getAppVersion`, and `reload` from the pinned native client.
Prefer the wrapper-managed flow unless the app needs explicit update controls.

## Compatibility strategies

The default `fingerprint` strategy only offers a release to a binary whose
embedded native fingerprint matches the release. Native dependencies,
platform source, build configuration, and other native-affecting changes can
change that fingerprint.

After a native-affecting change, refresh the configuration:

```bash
npx rollbird init
```

Then rebuild and distribute the native app before expecting it to receive the
next release. For Expo, run prebuild after refreshing the stored fingerprint:

```bash
npx expo prebuild
```

The optional `appVersion` strategy matches the application version instead.
Set it in the wrapper and identify the target when publishing:

```tsx
export default Rollbird.wrap({
  projectKey: "pk_from_rollbird_json",
  strategy: "appVersion",
})(App);
```

```bash
npx rollbird release --production --target-app-version 2.4.0 --yes
```

A channel is independent of the compatibility strategy. The binary requests
only the channel embedded by `rollbird init --channel <name>`.

## Update behavior

On launch, the wrapper asks Rollbird for a compatible release. A normal update
downloads in the background and becomes active on the next launch. If there is
no compatible release, the app continues with its current bundle.

A release published with `--force` reloads after download by default. Set
`reloadOnForceUpdate: false` only when the app owns the user experience and
will call `Rollbird.reload()` itself.

Download and update errors are passed to `onError`; the current bundle keeps
running. Telemetry beacons are best effort and never interrupt the app.

If a newly installed bundle crashes before reporting ready, the native client
recovers to the previous safe bundle. Rollbird records a `RECOVERED` launch as
an install failure for the crashed release.

## Bare React Native configuration

For a bare project, `rollbird init` writes the channel, public signing key,
project key, runtime, and fingerprint into the existing iOS and Android native
configuration. It wires the entry points that load the selected bundle.

Do not hand-copy those values between targets. Re-run `rollbird init` for the
desired channel, inspect the diff, and rebuild the binary.

## Expo configuration

For an Expo project, `rollbird init` registers the `@rollbird/react-native`
config plugin and stores the public configuration and per-platform
fingerprints in `rollbird.json`. The plugin applies those values during
prebuild.

If the Expo config is JavaScript or TypeScript, add the generated plugin entry
to the returned `plugins` array because the CLI does not rewrite executable
config files.

Rollbird refuses a project with `expo-updates` installed. Both packages control
the update process and must not coexist.

## Rollback and recovery

An operator rollback disables the selected release and makes the previous
valid release the next bundle offered on that channel. If none remains, the
app returns to its embedded bundle. A binary never moves below the bundle it
shipped with.

Rollback is always free. It does not consume release quota and remains
available when plan status or storage prevents a new release.
