# Quick start


`@flareapp/react-native` is Flare's SDK for [React Native](https://reactnative.dev). It catches errors in your mobile app and reports them to Flare with device and app context attached.

It is **pure JavaScript** and works on both [Expo](https://expo.dev) (managed) and bare React Native projects. There is no native module to link and no `pod install` step: you install it like any other JavaScript package.

If you are new to React Native, the only thing you need to know to follow this guide is where your app's **entry file** is. That is the file React Native runs first, usually `App.tsx`, `App.js`, or `index.js` at the root of your project. Every snippet below goes in or near that file.

## Requirements

- **React Native 0.79 or newer** (or **Expo SDK 53 or newer**). The SDK relies on Metro's package-exports support, which is on by default from React Native 0.79. On older versions Metro cannot resolve the package; see [Troubleshooting](#troubleshooting).
- **React 18 or 19** (whatever your React Native version already uses).

## Installing the packages

Install the React Native SDK and the React integration it builds on:

```bash
npm install @flareapp/react-native @flareapp/react
# or
yarn add @flareapp/react-native @flareapp/react
# or
pnpm add @flareapp/react-native @flareapp/react
```

That is everything you need. `react` and `react-native` are already in your project, and the Flare core is pulled in for you. You do **not** need `@flareapp/js` (that is the browser client).

## Setting up the Flare client

Initialize Flare as early as possible, at the top of your entry file. Calling `flare.light()` with your project key turns reporting on:

```ts
// App.tsx
import { flare } from '@flareapp/react-native';

flare.light('YOUR PROJECT KEY');
```

You can find the project key on the project settings page in Flare, below the project configuration section.

It is common to only enable Flare in production so development errors do not create noise. React Native exposes a global `__DEV__` flag you can guard with:

```ts
import { flare } from '@flareapp/react-native';

if (!__DEV__) {
    flare.light('YOUR PROJECT KEY');
}
```

## Wrapping your app in the error boundary

`flare.light()` already catches uncaught JavaScript errors and unhandled promise rejections. To also catch errors thrown while React is rendering your components, wrap your app in `FlareErrorBoundary`:

```tsx
// App.tsx
import React from 'react';
import { flare, FlareErrorBoundary } from '@flareapp/react-native';

flare.light('YOUR PROJECT KEY');

export default function App() {
    return (
        <FlareErrorBoundary>
            <Root />
        </FlareErrorBoundary>
    );
}
```

Import `FlareErrorBoundary` from `@flareapp/react-native` (not from `@flareapp/react`). The React Native build wires the boundary to the mobile Flare client for you.

The boundary reports render errors with the React component stack attached. You can give it a `fallback` to show your own UI instead of a blank screen after a crash:

```tsx
<FlareErrorBoundary fallback={<Text>Something went wrong.</Text>}>
    <Root />
</FlareErrorBoundary>
```

See the [Error boundary docs](/docs/react/errors/error-boundary) for the full list of props (`fallback`, `resetKeys`, `onReset`, and the `beforeSubmit` / `afterSubmit` hooks). They work the same as in the web React integration.

## What Flare captures automatically

Once `flare.light()` has run, you get three kinds of capture with no extra setup:

- **Uncaught JavaScript errors.** Anything that bubbles up to React Native's global error handler.
- **Unhandled promise rejections.** A `Promise` that rejects with no `.catch()`. This works on both the Hermes and JSC JavaScript engines.
- **React render errors.** These are captured once you add the `FlareErrorBoundary` above.

Each report includes device and app context: platform and OS version, screen dimensions, and (on Expo) the device model and app version.

## Readable stack traces in production

In a release build, React Native minifies your JavaScript (and Hermes compiles it to bytecode), so production stack traces point at a minified bundle instead of your source. To get readable file names, line numbers, and code snippets back, upload sourcemaps with the `@flareapp/react-native-sourcemaps` package. See [Sourcemaps](/docs/react-native/errors/sourcemaps).

## Identifying the user

Attach the signed-in user so you can see who hit an error. Call this after you know who the user is (for example, right after login):

```ts
import { flare } from '@flareapp/react-native';

flare.setUser({
    id: 1,
    email: 'user@example.com',
    fullName: 'Jane Doe',
});
```

All fields are optional. Pass `flare.setUser(null)` on logout to clear it.

## Adding breadcrumbs and context

Use `flare.glow()` to leave breadcrumbs ("glows") that show up on the error's timeline, and the context helpers to attach extra data. These are shared with the core JavaScript client:

```ts
import { flare } from '@flareapp/react-native';

flare.glow('Checkout started', 'info', { cartId: 42 });
```

- [Adding glows](/docs/javascript/data-collection/adding-glows)
- [Adding custom context](/docs/javascript/data-collection/adding-custom-context)

## Reporting errors manually

To report an error you caught yourself (for example in a `try/catch`), call `flare.report()`:

```ts
import { flare } from '@flareapp/react-native';

try {
    await loadProfile();
} catch (error) {
    flare.report(error as Error);
}
```

See [Reporting errors](/docs/javascript/errors/reporting-errors) and [Client hooks](/docs/javascript/errors/client-hooks) for filtering and enriching reports before they are sent.

## Richer device context with Expo (optional)

If your project uses Expo, install Expo's device and application modules to add the device model, OS name, and app version to every report:

```bash
npx expo install expo-device expo-application
```

The SDK detects these packages automatically. If they are not installed (a bare React Native app without them), Flare simply leaves those fields out. There is nothing to configure.

## Verifying your setup

Trigger a test error and check that it shows up on your Flare dashboard. The simplest way is to report one on a button press:

```tsx
import { Button } from 'react-native';
import { flare } from '@flareapp/react-native';

<Button title="Test Flare" onPress={() => flare.test()} />;
```

Run your app, tap the button, and the error should appear in your project within a few seconds.

If nothing arrives, enable debug logging to see what the client is doing. Pass `true` as the second argument to `light()`, or call `configure`:

```ts
flare.light('YOUR PROJECT KEY', true);
// or
flare.configure({ debug: true });
```

## What is not included yet

- **Native crashes.** Crashes in native (Java/Kotlin, Objective-C/Swift) code are not captured, only JavaScript errors. Native crash capture would require a native module, which this pure-JS SDK intentionally avoids.
- **Tracing and component profiling.** In a web app, Flare's tracing follows page loads, client-side navigations, and the requests your page makes while it loads. React Native has none of that: there is no browser page load and no URL-based router to trace. `@flareapp/react-native` reports errors only, so this SDK has no tracing or profiling pages.

Delivery is **best-effort**: reports are sent with `fetch`, which React Native does not back with `keepalive`. A report fired during a hard crash or while the app is being backgrounded may not finish sending.

## Troubleshooting

**Metro error: `Unable to resolve module node:module`.** Your React Native version is older than 0.79, so Metro is bundling the wrong build of the SDK. Upgrade to React Native 0.79+ (or Expo SDK 53+).

**Metro error: `Unable to resolve module @flareapp/react/inject`.** Same cause. The error boundary uses a package-exports subpath that needs Metro's package-exports support, on by default from React Native 0.79.

**Errors are not reported in development.** This is by design if you used the `__DEV__` guard above. Test with a release build, or temporarily call `flare.light('YOUR PROJECT KEY')` without the guard.
