- name
- sentry-react-native-sdk
- description
- Full Sentry SDK setup for React Native and Expo. Use when asked to "add Sentry to React Native", "install @sentry/react-native", "setup Sentry in Expo", or configure error monitoring, tracing, profiling, session replay, or logging for React Native applications. Supports Expo managed, Expo bare, and vanilla React Native.
- license
- Apache-2.0
- category
- sdk-setup
- parent
- sentry-sdk-setup
- disable-model-invocation
- true
> [All Skills](../../SKILL_TREE.md) > [SDK Setup](../sentry-sdk-setup/SKILL.md) > React Native SDK
# Sentry React Native SDK
Opinionated wizard that scans your React Native or Expo project and guides you through complete Sentry setup — error monitoring, tracing, profiling, session replay, logging, and more.
## Invoke This Skill When
- User asks to "add Sentry to React Native" or "set up Sentry" in an RN or Expo app
- User wants error monitoring, tracing, profiling, session replay, or logging in React Native
- User mentions `@sentry/react-native`, mobile error tracking, or Sentry for Expo
- User wants to monitor native crashes, ANRs, or app hangs on iOS/Android
> **Note:** SDK versions and APIs below reflect current Sentry docs at time of writing (`@sentry/react-native` ≥6.0.0, minimum recommended ≥8.0.0).
> Always verify against [docs.sentry.io/platforms/react-native/](https://docs.sentry.io/platforms/react-native/) before implementing.
---
## Phase 1: Detect
Run these commands to understand the project before making any recommendations:
```bash
# Detect project type and existing Sentry
cat package.json | grep -E '"(react-native|expo|@expo|@sentry/react-native|sentry-expo)"'
# Distinguish Expo managed vs bare vs vanilla RN
ls app.json app.config.js app.config.ts 2>/dev/null
cat app.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('Expo managed' if 'expo' in d else 'Bare/Vanilla')" 2>/dev/null
# Check Expo SDK version (important: Expo SDK 50+ required for @sentry/react-native)
cat package.json | grep '"expo"'
# Detect navigation library
grep -E '"(@react-navigation/native|react-native-navigation)"' package.json
# Detect state management (Redux → breadcrumb integration available)
grep -E '"(redux|@reduxjs/toolkit|zustand|mobx)"' package.json
# Check for existing Sentry initialization
grep -r "Sentry.init" src/ app/ App.tsx App.js _layout.tsx 2>/dev/null | head -5
# Detect Hermes (affects source map handling)
cat android/app/build.gradle 2>/dev/null | grep -i hermes
cat ios/Podfile 2>/dev/null | grep -i hermes
# Detect Expo Router
ls app/_layout.tsx app/_layout.js 2>/dev/null
# Detect backend for cross-link
ls backend/ server/ api/ 2>/dev/null
find . -maxdepth 3 \( -name "go.mod" -o -name "requirements.txt" -o -name "Gemfile" -o -name "package.json" \) 2>/dev/null | grep -v node_modules | head -10
```
**What to determine:**
| Question | Impact |
|----------|--------|
| `expo` in `package.json`? | Expo path (config plugin + `getSentryExpoConfig`) vs bare/vanilla RN path |
| Expo SDK ≥50? | `@sentry/react-native` directly; older = `sentry-expo` (legacy, do not use) |
| `app.json` has `"expo"` key? | Managed Expo — wizard is simplest; config plugin handles all native config |
| `app/_layout.tsx` present? | Expo Router project — init goes in `_layout.tsx` |
| `@sentry/react-native` already in `package.json`? | Skip install, jump to feature config |
| `@react-navigation/native` present? | Recommend `reactNavigationIntegration` for screen tracking |
| `react-native-navigation` present? | Recommend `reactNativeNavigationIntegration` (Wix) |
| Backend directory detected? | Trigger Phase 4 cross-link |
---
## Phase 2: Recommend
Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal:
**Recommended (core coverage — always set up these):**
- ✅ **Error Monitoring** — captures JS exceptions, native crashes (iOS + Android), ANRs, and app hangs
- ✅ **Tracing** — mobile performance is critical; auto-instruments navigation, app start, network requests
- ✅ **Session Replay** — mobile replay captures screenshots and touch events for debugging user issues
**Optional (enhanced observability):**
- ⚡ **Profiling** — CPU profiling on iOS (JS profiling cross-platform); low overhead in production
- ⚡ **Logging** — structured logs via `Sentry.logger.*`; links to traces for full context
- ⚡ **User Feedback** — collect user-submitted bug reports directly from your app
**Recommendation logic:**
| Feature | Recommend when... |
|---------|------------------|
| Error Monitoring | **Always** — non-negotiable baseline for any mobile app |
| Tracing | **Always for mobile** — app start, navigation, and network latency matter |
| Session Replay | User-facing production app; debug user-reported issues visually |
| Profiling | Performance-sensitive screens, startup time concerns, or production perf investigations |
| Logging | App uses structured logging, or you want log-to-trace correlation in Sentry |
| User Feedback | Beta or customer-facing app where you want user-submitted bug reports |
Propose: *"For your [Expo managed / bare RN] app, I recommend setting up Error Monitoring + Tracing + Session Replay. Want me to also add Profiling and Logging?"*
---
## Phase 3: Guide
### Determine Your Setup Path
| Project type | Recommended setup | Complexity |
|-------------|------------------|------------|
| Expo managed (SDK 50+) | Wizard CLI or manual with config plugin | Low — wizard does everything |
| Expo bare (SDK 50+) | Wizard CLI recommended | Medium — handles iOS/Android config |
| Vanilla React Native (0.69+) | Wizard CLI recommended | Medium — handles Xcode + Gradle |
| Expo SDK <50 | Use `sentry-expo` (legacy) | See [legacy docs](https://docs.sentry.io/platforms/react-native/manual-setup/expo/) |
---
### Path A: Wizard CLI (Recommended for all project types)
> **You need to run this yourself** — the wizard opens a browser for login and requires interactive input that the agent can't handle. Copy-paste into your terminal:
>
> ```
> npx @sentry/wizard@latest -i reactNative
> ```
>
> It handles login, org/project selection, SDK installation, native config, source map upload, and `Sentry.init()`. Here's what it creates/modifies:
>
> | File | Action | Purpose |
> |------|--------|---------|
> | `package.json` | Installs `@sentry/react-native` | Core SDK |
> | `metro.config.js` | Adds `@sentry/react-native/metro` serializer | Source map generation |
> | `app.json` | Adds `@sentry/react-native/expo` plugin (Expo only) | Config plugin for native builds |
> | `App.tsx` / `_layout.tsx` | Adds `Sentry.init()` and `Sentry.wrap()` | SDK initialization |
> | `ios/sentry.properties` | Stores org/project/token | iOS source map + dSYM upload |
> | `android/sentry.properties` | Stores org/project/token | Android source map upload |
> | `android/app/build.gradle` | Adds Sentry Gradle plugin | Android source maps + proguard |
> | `ios/[AppName].xcodeproj` | Wraps "Bundle RN" build phase + adds dSYM upload | iOS symbol upload |
> | `.env.local` | `SENTRY_AUTH_TOKEN` | Auth token (add to `.gitignore`) |
>
> **Once it finishes, come back and skip to [Verification](#verification).**
If the user skips the wizard, proceed with Path B or C (Manual Setup) below based on their project type.
---
### Path B: Manual — Expo Managed (SDK 50+)
**Step 1 — Install**
```bash
npx expo install @sentry/react-native
```
**Step 2 — `metro.config.js`**
```javascript
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
const config = getSentryExpoConfig(__dirname, {
// Auto-wrap Expo Router ErrorBoundary exports at build time (SDK ≥8.17.0)
autoWrapExpoRouterErrorBoundary: true,
});
module.exports = config;
```
If `metro.config.js` doesn't exist yet:
```bash
npx expo customize metro.config.js
# Then replace contents with the above
```
**Metro config options:**
| Option | Type | Default | Purpose |
|--------|------|---------|---------|
| `autoWrapExpoRouterErrorBoundary` | `boolean` | `false` | Automatically wrap `export { ErrorBoundary } from 'expo-router'` with Sentry at build time (SDK ≥8.17.0). Captures errors that hit per-route ErrorBoundaries without manual wrapping |
| `annotateReactComponents` | `boolean` | `false` | Inject component names for better error context |
| `includeWebReplay` | `boolean` | `true` | Include web replay bundle (set `false` for native-only apps) |
| `includeWebFeedback` | `boolean` | `true` | Include web feedback bundle (set `false` for native-only apps) |
| `enableSourceContextInDevelopment` | `boolean` | `true` | Enable source context in dev builds |
**Step 3 — `app.json` — Add Expo config plugin**
```json
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"url": "https://sentry.io/",
"project": "YOUR_PROJECT_SLUG",
"organization": "YOUR_ORG_SLUG",
"disableAutoUpload": false
}
]
]
}
}
```
> **Note:** Set `SENTRY_AUTH_TOKEN` as an environment variable for native builds — never commit it to version control.
**Plugin options:**
| Option | Type | Default | Purpose |
|--------|------|---------|---------|
| `url` | `string` | `"https://sentry.io/"` | Sentry instance URL |
| `project` | `string` | — | Project slug |
| `organization` | `string` | — | Organization slug |
| `disableAutoUpload` | `boolean` | `false` | Skip source map + dSYM upload during local builds (SDK ≥8.13.0) |
**Step 4 — Initialize Sentry**
For **Expo Router** (`app/_layout.tsx`):
```typescript
import { Stack } from "expo-router";
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN ?? "YOUR_SENTRY_DSN",
sendDefaultPii: true,
// Tracing
tracesSampleRate: 1.0, // lower to 0.1–0.2 in production
// Profiling
profilesSampleRate: 1.0,
// Session Replay
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
// Logging (SDK ≥7.0.0)
enableLogs: true,
// Session Replay
integrations: [
Sentry.mobileReplayIntegration(),
],
enableNativeFramesTracking: !isRunningInExpoGo(), // slow/frozen frames
environment: __DEV__ ? "development" : "production",
});
function RootLayout() {
return <Stack />;
}
export default Sentry.wrap(RootLayout);
```
> **Note:** Expo Router automatically handles navigation tracking. The `Sentry.NavigationContainer` wrapper is not needed for Expo Router projects — navigation spans are captured automatically.
**Expo Router ErrorBoundary Setup (SDK ≥8.16.0)**
Expo Router's per-route `ErrorBoundary` swallows render errors by default — Sentry won't see them unless you explicitly capture them. Two options:
1. **Auto-wrap (recommended, SDK ≥8.17.0)** — Enable `autoWrapExpoRouterErrorBoundary: true` in `metro.config.js` (shown above). The Babel plugin rewrites `export { ErrorBoundary } from 'expo-router'` automatically in all route files.
2. **Manual wrap** — Wrap the boundary yourself in each route file:
```typescript
// app/_layout.tsx (or any route file)
import { ErrorBoundary as ExpoErrorBoundary } from 'expo-router';
import * as Sentry from '@sentry/react-native';
export const ErrorBoundary = Sentry.wrapExpoRouterErrorBoundary(ExpoErrorBoundary);
```
Both methods capture errors that hit the boundary with route context (`route.name`, `route.path`, `route.params`), tag the active navigation span as errored, and emit a breadcrumb. Concrete paths/params respect `sendDefaultPii`.
For **standard Expo** (`App.tsx`):
```typescript
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN ?? "YOUR_SENTRY_DSN",
sendDefaultPii: true,
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
enableLogs: true,
integrations: [
Sentry.mobileReplayIntegration(),
],
enableNativeFramesTracking: !isRunningInExpoGo(),
environment: __DEV__ ? "development" : "production",
});
function App() {
return (
<Sentry.NavigationContainer>
{/* your navigation here */}
</Sentry.NavigationContainer>
);
}
export default Sentry.wrap(App);
```
---
### Path C: Manual — Bare React Native (0.69+)
**Step 1 — Install**
Ver en GitHub