Sentry Setup
Sentry is one of the most popular solution for error reporting in the javascript ecosystem and has a great integration with Expo, we have been using it for a while and it has been working very well.
The starter kit did not come with Sentry pre-configured, but it’s very easy to setup and this guide will walk you through the process.
Install and configure Sentry
-
Create a new Sentry account if you don’t have one already. Once logged in, create a new project for your React Native app.
-
During project creation, pay close attention to and note down the following important details:
-
Organization slug
-
Project name
-
DSN
we will use those details next to configure the Sentry SDK in your app.
-
-
Now you need also to generate a new Auth Token so you can use it to upload source maps to Sentry. To generate a new Auth Token you need to go to Developer Settings > Auth Tokens and create a new token.
- Copy and securely store the generated token. You’ll need this for configuring source map uploads.
-
At this point, you should have the following environment variables that need to be added to your
.env
files:Terminal window SENTRY_ORG=your_sentry_organization_slugSENTRY_PROJECT=your_sentry_project_nameSENTRY_DSN=your_sentry_dsnIt’s crucial to add these variables to
env.js
for validation.SENTRY_ORG
andSENTRY_PROJECT
should be added as build-time variables, whileSENTRY_DSN
should be added as a client variable.Update your
env.js
file as follows:env.js // ... existing imports and configurationsconst client = z.object({// ... other client env varsSENTRY_DSN: z.string().min(1, 'SENTRY_DSN is required'),});const buildTime = z.object({// ... other build-time env varsSENTRY_ORG: z.string().min(1, 'SENTRY_ORG is required'),SENTRY_PROJECT: z.string().min(1, 'SENTRY_PROJECT is required'),});const _clientEnv = {// ... other client env varsSENTRY_DSN: process.env.SENTRY_DSN,};const _buildTimeEnv = {// ... other build-time env varsSENTRY_ORG: process.env.SENTRY_ORG,SENTRY_PROJECT: process.env.SENTRY_PROJECT,};// ... rest of the file -
Now you can install the Sentry SDK in your project.
Terminal window npx expo install @sentry/react-native -
Add Sentry plugin config to your
app.config.ts
file.app.config.ts // rest of the fileimport { ClientEnv, Env } from './env';export default ({ config }: ConfigContext): ExpoConfig => ({...config,// rest of the configplugins: [// rest of the plugins['@sentry/react-native/expo',{url: 'https://sentry.io/',organization: Env.SENTRY_ORG,project: Env.SENTRY_PROJECT,note: 'Ensure you set the SENTRY_AUTH_TOKEN as an environment variable to authenticate with Sentry. Do not add it to the .env file. Instead, add it as an EAS secret or as an environment variable in your CI/CD pipeline for security.',// If you are using a self-hosted instance, update the value of the url property// to point towards your self-hosted instance. For example, https://self-hosted.example.com/.},],],}); -
Update your metro config to inject debug ID intro your source maps
metro.config.js /* eslint-env node */// this replaces `const { getDefaultConfig } = require('expo/metro-config');`const { getSentryExpoConfig } = require('@sentry/react-native/metro');const { withNativeWind } = require('nativewind/metro');const config = getSentryExpoConfig(__dirname);module.exports = withNativeWind(config, { input: './global.css' }); -
Now you are ready to initialize Sentry in your app. Create a new file
src/lib/sentry.ts
and add the following code:src/lib/sentry.ts import { Env } from '@env';import * as Sentry from '@sentry/react-native';import { useNavigationContainerRef } from 'expo-router';import { useEffect } from 'react';const navigationIntegration = Sentry.reactNavigationIntegration({enableTimeToInitialDisplay: true,});export const initSentry = () => {if (!__DEV__) {Sentry.init({dsn: Env.SENTRY_DSN,integrations: [navigationIntegration],});}};export const useSentryNavigationConfig = () => {const navigationRef = useNavigationContainerRef();useEffect(() => {if (navigationRef && !__DEV__) {navigationIntegration.registerNavigationContainer(navigationRef);}}, [navigationRef]);};Then, initialize Sentry and configure it with navigation in your
src/app/_layout.tsx
file:src/app/_layout.tsx import { initSentry, useSentryNavigationConfig } from '@/lib/sentry';import * as Sentry from '@sentry/react-native';initSentry();function RootLayout() {useSentryNavigationConfig();return (<Providers><Stack><Stack.Screen name="(app)" options={{ headerShown: false }} /><Stack.Screen name="onboarding" options={{ headerShown: false }} />...</Stack></Providers>);}// Wrap your app with Sentryexport default Sentry.wrap(RootLayout);This setup will enable Sentry error tracking and performance monitoring in your app.
-
One last thing is to add Apple privacy manifest to prevent any issues with Apple. Create a new file
apple-privacy-manifest.json
and add the following code:apple-privacy-manifest.json {"NSPrivacyCollectedDataTypes": [{"NSPrivacyCollectedDataType": "NSPrivacyCollectedDataTypeCrashData","NSPrivacyCollectedDataTypeLinked": false,"NSPrivacyCollectedDataTypeTracking": false,"NSPrivacyCollectedDataTypePurposes": ["NSPrivacyCollectedDataTypePurposeAppFunctionality"]},{"NSPrivacyCollectedDataType": "NSPrivacyCollectedDataTypePerformanceData","NSPrivacyCollectedDataTypeLinked": false,"NSPrivacyCollectedDataTypeTracking": false,"NSPrivacyCollectedDataTypePurposes": ["NSPrivacyCollectedDataTypePurposeAppFunctionality"]},{"NSPrivacyCollectedDataType": "NSPrivacyCollectedDataTypeOtherDiagnosticData","NSPrivacyCollectedDataTypeLinked": false,"NSPrivacyCollectedDataTypeTracking": false,"NSPrivacyCollectedDataTypePurposes": ["NSPrivacyCollectedDataTypePurposeAppFunctionality"]}],"NSPrivacyAccessedAPITypes": [{"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryUserDefaults","NSPrivacyAccessedAPITypeReasons": ["CA92.1"]},{"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategorySystemBootTime","NSPrivacyAccessedAPITypeReasons": ["35F9.1"]},{"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryFileTimestamp","NSPrivacyAccessedAPITypeReasons": ["C617.1"]}]}Then add it to your
app.config.ts
app.config.ts import applePrivacyManifest from './apple-privacy-manifest.json';export default ({ config }: ConfigContext): ExpoConfig => ({...config,// rest of the configios: {// rest of ios configprivacyManifests: applePrivacyManifest,},});Read more about Apple Privacy Manifest and sentry
-
Now you are ready to test Sentry integration. Follow these steps to ensure errors are being reported correctly:
- Run the prebuild command for your project.
- Launch the app in a simulator or on a physical device.
- Use the following code snippet to add error-triggering buttons to your app:
import React from 'react';import { View, Button } from 'react-native';import * as Sentry from '@sentry/react-native';const SentryTestComponent = () => {const throwJSError = () => {throw new Error('Test JavaScript Error for Sentry');};const triggerNativeError = () => {Sentry.nativeCrash();};return (<View><Button title="Trigger JS Error" onPress={throwJSError} /><Button title="Trigger Native Error" onPress={triggerNativeError} /></View>);};export default SentryTestComponent;- Implement this component in your app and interact with the buttons.
- Check your Sentry dashboard to verify that the errors are being reported correctly (make sure to wait a little bit for the errors to appear).
Remember to remove or disable these test buttons before releasing your app to production.