Labsco
getsentry logo

sentry-react-native-sdk

✓ Official19

by sentry · part of getsentry/sentry-agent-skills

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…

🔥🔥🔥🔥✓ VerifiedAccount requiredNeeds API keys
🧩 One of 7 skills in the getsentry/sentry-agent-skills package — works on its own, and pairs well with its siblings.

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…

Inspect the full instructions your agent will receiveExpand

This is the exact playbook injected into your agent when the skill activates — shown here so you can audit it before installing. You don't need to read it to use the skill.

by sentry

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… npx skills add https://github.com/getsentry/agent-skills --skill sentry-react-native-sdk Download ZIPGitHub19

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/ before implementing.

Phase 1: Detect

Run these commands to understand the project before making any recommendations:

Copy & paste — that's it
# 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

Path A: Wizard CLI (Recommended for all project types)

Run the wizard — it walks you through login, org/project selection, and auth token setup interactively. It then handles installation, native config, source map upload, and initial Sentry.init():

Copy & paste — that's it
npx @sentry/wizard@latest -i reactNative

What the wizard 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)

After the wizard runs, skip to Verification .

Path B: Manual — Expo Managed (SDK 50+)

Step 1 — Install

Copy & paste — that's it
npx expo install @sentry/react-native

Step 2 — metro.config.js

Copy & paste — that's it
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
const config = getSentryExpoConfig(__dirname);
module.exports = config;

If metro.config.js doesn't exist yet:

Copy & paste — that's it
npx expo customize metro.config.js
# Then replace contents with the above

Step 3 — app.json — Add Expo config plugin

Copy & paste — that's it
{
 "expo": {
 "plugins": [
 [
 "@sentry/react-native/expo",
 {
 "url": "https://sentry.io/",
 "project": "YOUR_PROJECT_SLUG",
 "organization": "YOUR_ORG_SLUG"
 }
 ]
 ]
 }
}

Note: Set SENTRY_AUTH_TOKEN as an environment variable for native builds — never commit it to version control.

Step 4 — Initialize Sentry

For Expo Router (app/_layout.tsx):

Copy & paste — that's it
import { Stack, useNavigationContainerRef } from "expo-router";
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";
import React from "react";

const navigationIntegration = Sentry.reactNavigationIntegration({
 enableTimeToInitialDisplay: !isRunningInExpoGo(), // disabled in Expo Go
});

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,

 // Navigation
 integrations: [
 navigationIntegration,
 Sentry.mobileReplayIntegration(),
 ],

 enableNativeFramesTracking: !isRunningInExpoGo(), // slow/frozen frames

 environment: __DEV__ ? "development" : "production",
});

function RootLayout() {
 const ref = useNavigationContainerRef();

 React.useEffect(() => {
 if (ref) {
 navigationIntegration.registerNavigationContainer(ref);
 }
 }, [ref]);

 return ;
}

export default Sentry.wrap(RootLayout);

For standard Expo (App.tsx):

Copy & paste — that's it
import { NavigationContainer, createNavigationContainerRef } from "@react-navigation/native";
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";

const navigationIntegration = Sentry.reactNavigationIntegration({
 enableTimeToInitialDisplay: !isRunningInExpoGo(),
});

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: [
 navigationIntegration,
 Sentry.mobileReplayIntegration(),
 ],
 enableNativeFramesTracking: !isRunningInExpoGo(),
 environment: __DEV__ ? "development" : "production",
});

const navigationRef = createNavigationContainerRef();

function App() {
 return (
 {
 navigationIntegration.registerNavigationContainer(navigationRef);
 }}
 >
 {/* your navigation here */}
 
 );
}

export default Sentry.wrap(App);

Path C: Manual — Bare React Native (0.69+)

Step 1 — Install

Copy & paste — that's it
npm install @sentry/react-native --save
cd ios && pod install

Step 2 — metro.config.js

Copy & paste — that's it
const { getDefaultConfig } = require("@react-native/metro-config");
const { withSentryConfig } = require("@sentry/react-native/metro");

const config = getDefaultConfig(__dirname);
module.exports = withSentryConfig(config);

Step 3 — iOS: Modify Xcode build phase

Open ios/[AppName].xcodeproj in Xcode. Find the "Bundle React Native code and images" build phase and replace the script content with:

Copy & paste — that's it
# RN 0.81.1+
set -e
WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
SENTRY_XCODE="../node_modules/@sentry/react-native/scripts/sentry-xcode.sh"
/bin/sh -c "$WITH_ENVIRONMENT $SENTRY_XCODE"

Step 4 — iOS: Add "Upload Debug Symbols to Sentry" build phase

Add a new Run Script build phase in Xcode (after the bundle phase):

Copy & paste — that's it
/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh

Step 5 — iOS: ios/sentry.properties

Copy & paste — that's it
defaults.url=https://sentry.io/
defaults.org=YOUR_ORG_SLUG
defaults.project=YOUR_PROJECT_SLUG
auth.token=YOUR_ORG_AUTH_TOKEN

Step 6 — Android: android/app/build.gradle

Add before the android {} block:

Copy & paste — that's it
apply from: "../../node_modules/@sentry/react-native/sentry.gradle"

Step 7 — Android: android/sentry.properties

Copy & paste — that's it
defaults.url=https://sentry.io/
defaults.org=YOUR_ORG_SLUG
defaults.project=YOUR_PROJECT_SLUG
auth.token=YOUR_ORG_AUTH_TOKEN

Step 8 — Initialize Sentry (App.tsx or entry point)

Copy & paste — that's it
import { NavigationContainer, createNavigationContainerRef } from "@react-navigation/native";
import * as Sentry from "@sentry/react-native";

const navigationIntegration = Sentry.reactNavigationIntegration({
 enableTimeToInitialDisplay: true,
});

Sentry.init({
 dsn: "YOUR_SENTRY_DSN",
 sendDefaultPii: true,
 tracesSampleRate: 1.0,
 profilesSampleRate: 1.0,
 replaysOnErrorSampleRate: 1.0,
 replaysSessionSampleRate: 0.1,
 enableLogs: true,
 integrations: [
 navigationIntegration,
 Sentry.mobileReplayIntegration(),
 ],
 enableNativeFramesTracking: true,
 environment: __DEV__ ? "development" : "production",
});

const navigationRef = createNavigationContainerRef();

function App() {
 return (
 {
 navigationIntegration.registerNavigationContainer(navigationRef);
 }}
 >
 {/* your navigation here */}
 
 );
}

export default Sentry.wrap(App);

Quick Reference: Full-Featured Sentry.init()

This is the recommended starting configuration with all features enabled:

Copy & paste — that's it
import * as Sentry from "@sentry/react-native";

Sentry.init({
 dsn: "YOUR_SENTRY_DSN",
 sendDefaultPii: true,

 // Tracing — lower to 0.1–0.2 in high-traffic production
 tracesSampleRate: 1.0,

 // Profiling — runs on a subset of traced transactions
 profilesSampleRate: 1.0,

 // Session Replay — always capture on error, sample 10% of all sessions
 replaysOnErrorSampleRate: 1.0,
 replaysSessionSampleRate: 0.1,

 // Logging — enable Sentry.logger.* API
 enableLogs: true,

 // Integrations — mobile replay is opt-in
 integrations: [
 Sentry.mobileReplayIntegration({
 maskAllText: true, // masks text by default for privacy
 maskAllImages: true,
 }),
 ],

 // Native frames tracking (disable in Expo Go)
 enableNativeFramesTracking: true,

 // Environment
 environment: __DEV__ ? "development" : "production",

 // Release — set from CI or build system
 // release: "[email protected]+1",
 // dist: "1",
});

// REQUIRED: Wrap root component to capture React render errors
export default Sentry.wrap(App);

Navigation Setup — React Navigation (v5+)

Copy & paste — that's it
import { reactNavigationIntegration } from "@sentry/react-native";
import { NavigationContainer, createNavigationContainerRef } from "@react-navigation/native";

const navigationIntegration = reactNavigationIntegration({
 enableTimeToInitialDisplay: true, // track TTID per screen
 routeChangeTimeoutMs: 1_000, // max wait for route change to settle
 ignoreEmptyBackNavigationTransactions: true,
});

// Add to Sentry.init integrations array
Sentry.init({
 integrations: [navigationIntegration],
 // ...
});

// In your component:
const navigationRef = createNavigationContainerRef();

 {
 navigationIntegration.registerNavigationContainer(navigationRef);
 }}
>

Navigation Setup — Wix React Native Navigation

Copy & paste — that's it
import * as Sentry from "@sentry/react-native";
import { Navigation } from "react-native-navigation";

Sentry.init({
 integrations: [Sentry.reactNativeNavigationIntegration({ navigation: Navigation })],
 // ...
});

Wrap Your Root Component

Always wrap your root component — this enables React error boundaries and ensures crashes at the component tree level are captured:

Copy & paste — that's it
export default Sentry.wrap(App);

For Each Agreed Feature

Walk through features one at a time. Load the reference file for each, follow its steps, then verify before moving on:

Feature Reference Load when... Error Monitoring ${SKILL_ROOT}/references/error-monitoring.md Always (baseline) Tracing & Performance ${SKILL_ROOT}/references/tracing.md Always for mobile (app start, navigation, network) Profiling ${SKILL_ROOT}/references/profiling.md Performance-sensitive production apps Session Replay ${SKILL_ROOT}/references/session-replay.md User-facing apps Logging ${SKILL_ROOT}/references/logging.md Structured logging / log-to-trace correlation User Feedback ${SKILL_ROOT}/references/user-feedback.md Collecting user-submitted reports

For each feature: Read ${SKILL_ROOT}/references/<feature>.md, follow steps exactly, verify it works.

Environment Variables

Variable Purpose Notes SENTRY_DSN Data Source Name Falls back from dsn option SENTRY_AUTH_TOKEN Upload source maps and dSYMs Never commit — use CI secrets SENTRY_ORG Organization slug Used by wizard and build plugins SENTRY_PROJECT Project slug Used by wizard and build plugins SENTRY_RELEASE Release identifier Falls back from release option SENTRY_ENVIRONMENT Environment name Falls back from environment option SENTRY_DISABLE_AUTO_UPLOAD Skip source map upload Set true during local builds EXPO_PUBLIC_SENTRY_DSN Expo public env var for DSN Safe to embed in client bundle

Source Maps & Debug Symbols

Source maps and debug symbols are what transform minified stack traces into readable ones. When set up correctly, Sentry shows you the exact line of your source code that threw.

How Uploads Work

Platform What's uploaded When iOS (JS) Source maps (.map files) During Xcode build iOS (Native) dSYM bundles During Xcode archive / Xcode Cloud Android (JS) Source maps + Hermes .hbc.map During Gradle build Android (Native) Proguard mapping + NDK .so files During Gradle build

Expo: Automatic Upload

The @sentry/react-native/expo config plugin automatically sets up upload hooks for native builds. Source maps are uploaded during eas build and expo run:ios/android (release).

Copy & paste — that's it
SENTRY_AUTH_TOKEN=sntrys_... npx expo run:ios --configuration Release

Manual Upload (bare RN)

If you need to manually upload source maps:

Copy & paste — that's it
npx sentry-cli sourcemaps upload \
 --org YOUR_ORG \
 --project YOUR_PROJECT \
 --release "[email protected]+1" \
 ./dist

Default Integrations (Auto-Enabled)

These integrations are enabled automatically — no config needed:

Integration What it does ReactNativeErrorHandlers Catches unhandled JS exceptions and promise rejections Release Attaches release/dist to all events Breadcrumbs Records console logs, HTTP requests, user gestures as breadcrumbs HttpClient Adds HTTP request/response breadcrumbs DeviceContext Attaches device/OS/battery info to events AppContext Attaches app version, bundle ID, and memory info CultureContext Attaches locale and timezone Screenshot Captures screenshot on error (when attachScreenshot: true) ViewHierarchy Attaches view hierarchy (when attachViewHierarchy: true) NativeLinkedErrors Links JS errors to their native crash counterparts

Opt-In Integrations

Integration How to enable mobileReplayIntegration() Add to integrations array reactNavigationIntegration() Add to integrations array reactNativeNavigationIntegration() Add to integrations array (Wix only) feedbackIntegration() Add to integrations array (user feedback widget)

Expo Config Plugin Reference

Configure the plugin in app.json or app.config.js:

Copy & paste — that's it
{
 "expo": {
 "plugins": [
 [
 "@sentry/react-native/expo",
 {
 "url": "https://sentry.io/",
 "project": "my-project",
 "organization": "my-org",
 "note": "Set SENTRY_AUTH_TOKEN env var for native builds"
 }
 ]
 ]
 }
}

Or in app.config.js (allows env var interpolation):

Copy & paste — that's it
export default {
 expo: {
 plugins: [
 [
 "@sentry/react-native/expo",
 {
 url: "https://sentry.io/",
 project: process.env.SENTRY_PROJECT,
 organization: process.env.SENTRY_ORG,
 },
 ],
 ],
 },
};

Production Settings

Lower sample rates and harden config before shipping to production:

Copy & paste — that's it
Sentry.init({
 dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
 environment: __DEV__ ? "development" : "production",

 // Trace 10–20% of transactions in high-traffic production
 tracesSampleRate: __DEV__ ? 1.0 : 0.1,

 // Profile 100% of traced transactions (profiling is always a subset of tracing)
 profilesSampleRate: 1.0,

 // Replay all error sessions, sample 5% of normal sessions
 replaysOnErrorSampleRate: 1.0,
 replaysSessionSampleRate: __DEV__ ? 1.0 : 0.05,

 // Set release and dist for accurate source map lookup
 release: "my-app@" + Application.nativeApplicationVersion,
 dist: String(Application.nativeBuildVersion),

 // Disable debug logging in production
 debug: __DEV__,
});

Verification

After setup, test that Sentry is receiving events:

Copy & paste — that's it
// Quick test — throws and Sentry.wrap(App) catches it
 {
 throw new Error("My first Sentry error!");
 }}
/>

// Or capture manually
 {
 Sentry.captureMessage("Sentry test message", "info");
 }}
/>

Check the Sentry dashboard:

  • Issues → your test error should appear within seconds

  • Traces → look for a "main" transaction with child spans

  • Replays → session recording visible after app interaction (native build only — not Expo Go)

  • Logs → structured log entries if enableLogs: true

⚠️ Expo Go limitation: Native crashes, session replay, slow/frozen frames, TTID, and TTFD only work in native builds (eas build or expo run). Expo Go runs in a JS-only mode. Set enableNativeFramesTracking: !isRunningInExpoGo() to avoid warnings.

If nothing appears:

  • Set debug: true — SDK logs to Metro console

  • Verify DSN is correct and the Sentry project exists

  • Ensure Sentry.wrap(App) is applied to the root component

  • For native crashes, build a release build (crashes in debug mode may not forward)

Phase 4: Cross-Link

After completing React Native setup, check for a backend or web frontend missing Sentry coverage:

Copy & paste — that's it
# Adjacent backend directories
ls ../backend ../server ../api 2>/dev/null
cat ../go.mod 2>/dev/null | head -3
cat ../requirements.txt ../pyproject.toml 2>/dev/null | head -3
cat ../Gemfile 2>/dev/null | head -3
ls ../backend/package.json ../server/package.json 2>/dev/null

# Web frontend in same or sibling repo
ls ../web ../frontend ../dashboard 2>/dev/null
cat ../web/package.json ../frontend/package.json 2>/dev/null | grep -E '"react"|"svelte"|"next"'

# Check for OpenTelemetry (for distributed tracing interop)
grep -r "opentelemetry" ../backend/go.mod ../server/requirements.txt 2>/dev/null

If a backend or web frontend exists without Sentry, suggest the matching skill:

Detected Suggest skill Go backend (go.mod) sentry-go-sdk Python backend (requirements.txt, pyproject.toml) sentry-python-sdk Ruby backend (Gemfile) sentry-ruby-sdk Node.js backend (Express, Fastify, etc.) @sentry/node — see docs.sentry.io/platforms/javascript/guides/express/ React / Next.js web sentry-react-sdk Svelte / SvelteKit web sentry-svelte-sdk

Distributed tracing setup — if the backend skill is added, configure tracePropagationTargets in React Native to propagate trace context to your API:

Copy & paste — that's it
Sentry.init({
 tracePropagationTargets: [
 "localhost",
 /^https:\/\/api\.yourapp\.com/,
 ],
 // ...
});

This links mobile transactions to backend traces in the Sentry waterfall view.