Skip to main content

Handling Errors and Logging

1. Using Global Error Handler

Property Description Usage
ErrorBoundary Component to catch JavaScript errors anywhere in the child component tree import { ErrorBoundary } from 'expo-error-boundary';
handleError Function to handle errors in the global error handler function handleError(error, errorInfo) { console.error(error, errorInfo); }

Example: Implementing Global Error Handler

import React from 'react';
import { ErrorBoundary } from 'expo-error-boundary';

const App = () => {
  return (
    <ErrorBoundary onError={handleError}>
      <YourApp />
    </ErrorBoundary>
  );
};

function handleError(error, errorInfo) {
  console.error('Caught an error:', error, errorInfo);
}
Note: Error boundaries are React components that catch JavaScript errors in their child component tree, log those errors, and display a fallback UI instead of the component that crashed.

2. Logging Errors

Method Description Usage
console.error() Logs an error message to the console console.error("An error occurred");
console.warn() Logs a warning message to the console console.warn("This is a warning");
console.log() Logs a message to the console console.log("Debug info");
Note: In Expo, console.log and console.error are supported but may not appear in the browser console during development.

Example: Using Sentry for Error Logging

import * as Sentry from "sentry-expo";

Sentry.init({
  dsn: "YOUR_DSN_HERE",
});

// Log an error
Sentry.captureException(new Error("Something went wrong"));

3. Implementing Error Boundaries

Property Description Usage
ErrorBoundary Component that catches JavaScript errors anywhere in its child tree import { ErrorBoundary } from 'expo-error-boundary';

Example: Basic Error Boundary Setup

import React from 'react';
import { ErrorBoundary } from 'expo-error-boundary';

const App = () => {
  return (
    <ErrorBoundary
      onError={(error, errorInfo) => {
        console.error('Caught an error:', error);
      }}
    >
      <MyApp />
    </ErrorBoundary>
  );
};
Note: Error boundaries are React components that catch JavaScript errors in their child component tree, log those errors, and display a fallback UI instead of the component that crashed.

Key Points

  • Error boundaries are React components that catch runtime errors in their child tree.
  • They do not catch errors in event handlers or asynchronous code (e.g., setTimeout, promises).
  • They are useful for graceful degradation in production environments.

4. Handling Async Errors

Method Description Notes
Expo.ErrorUtils Global error handler for async errors in Expo apps. Used to capture and report unhandled promise rejections.

Example: Setting up global error handler

import * as ErrorUtils from 'expo-errors';\n\nErrorUtils.setGlobalHandler((error) => {\n  console.error('Unhandled async error:', error);\n  // Send to crash reporting service\n});
Note: This handler is called for unhandled promise rejections and other async errors that occur in the app.

5. Using Sentry Integration

Example: Setting up Sentry with Expo

import * as Sentry from 'sentry-expo';

Sentry.init({
  dsn: &#34;YOUR_DSN_HERE&#34;,
  enableInExpoDevelopment: true,
  debug: false
});
Property Description Default
dsn Unique identifier for your Sentry project null
enableInExpoDevelopment Enables Sentry in Expo development mode false
debug Enables debug logging in Sentry SDK false
Note: Make sure to set enableInExpoDevelopment to true if you want to capture errors during development.

Example: Capturing an exception

try {
  throw new Error(&#34;Something went wrong!&#34;);
} catch (error) {
  Sentry.Native.captureException(error);
}

Example: Logging a message

Sentry.Native.captureMessage(&#34;User performed an action&#34;, {
  level: &#34;info&#34;
});

Sentry Integration Summary

  • Initialize Sentry with your DSN in your app entry point
  • Use Sentry.Native.captureException() to report errors
  • Use Sentry.Native.captureMessage() for logging messages
  • Enable development mode with enableInExpoDevelopment

6. Configuring Sentry

Example: Setting up Sentry with Expo

// Install Sentry SDK
// npm install @sentry/react-native

import * as Sentry from '@sentry/react-native';

// Initialize Sentry in your app entry point
Sentry.init({
  dsn: 'YOUR_SENTRY_DSN',
  enableAutoSessionTracking: true,
});

// Capture an exception
try {
  throw new Error('Something went wrong');
} catch (error) {
  Sentry.captureException(error);
}
Configuration Option Description Default Value Notes
dsn Sentry project DSN None Required for Sentry to function
enableAutoSessionTracking Enables automatic session tracking false Useful for performance monitoring
debug Enables debug logging in Sentry SDK false Useful for development and troubleshooting
release Release version of the app undefined Helps in tracking errors across versions
environment Environment name (e.g. production, staging) undefined Useful for filtering errors by environment
Note: Ensure that the DSN is correctly configured to avoid sending errors to the wrong project.
Warning: Sentry SDK requires proper configuration in both development and production environments to capture errors effectively.

Key Points for Sentry Configuration

  • DSN is mandatory to initialize Sentry
  • Enable session tracking for performance monitoring
  • Set release and environment to track errors across versions
  • Use debug mode during development for troubleshooting

7. Capturing Exceptions

Method Description Usage
Expo.ErrorReporter Reports errors to a remote service
import * as ErrorReporter from 'expo-error-reporter';

ErrorReporter.reportError(new Error('Something went wrong'));
ErrorBoundary Captures JavaScript errors in components
import { ErrorBoundary } from 'expo-error-boundary';

<ErrorBoundary
  onError={(error, errorInfo) => {
    console.error('Caught an error:', error);
  }}
>
  <MyComponent />
</ErrorBoundary>

Example: Reporting Unhandled Errors

import * as ErrorReporter from 'expo-error-reporter';

// Report unhandled errors
window.addEventListener('error', (event) => {
  ErrorReporter.reportError(event.error);
});

// Report unhandled promise rejections
window.addEventListener('unhandledrejection', (event) => {
  ErrorReporter.reportError(event.reason);
});
Note: ErrorBoundary only catches errors in React components, not native crashes or unhandled JS exceptions.

8. Adding Breadcrumbs

Example: Adding breadcrumbs to an Expo app

import { useEffect } from 'react';
import * as Sentry from 'sentry-expo';

function MyComponent() {
  useEffect(() => {
    Sentry.addBreadcrumb({
      category: 'navigation',
      message: 'User navigated to Home screen',
      data: {
        screen: 'Home',
        timestamp: Date.now()
      }
    });
  }, []);

  return <View><Text>Home Screen</Text></View>;
}
Breadcrumb Property Description Example Value
category Logical grouping of breadcrumb (e.g., navigation, api) 'navigation'
message Human-readable description of breadcrumb 'User clicked button'
data Additional context to associate with breadcrumb { screen: 'Home' }
timestamp ISO timestamp when breadcrumb was added 1678886400000
Note: Breadcrumbs are automatically captured for navigation events in Expo apps when using Sentry SDK.
Warning: Avoid adding too many breadcrumbs as they can impact performance and memory usage.

9. Customizing Error Messages

Property Description Example
error.message Readable error message Network request failed
error.code Standardized error code NETWORK_ERROR
error.details Additional context or stack trace
{
  "url": "https://api.example.com/data",
  "method": "GET"
}

Example: Custom Error Class

class CustomError extends Error {
  constructor(code, message, details) {
    super(message);
    this.code = code;
    this.details = details;
  }
}

// Usage
const error = new CustomError(
  'API_ERROR',
  'Failed to fetch data from API',
  { url: 'https://api.example.com/data', status: 500 }
);

console.log(error.message); // "Failed to fetch data from API"
console.log(error.code);    // "API_ERROR"
Note: Expo provides built-in error handling in development, but customizing messages helps with debugging and user experience.

10. Reporting Native Crashes

Property Description Values
expo-error-reports Enables crash reporting to Expo's error reporting service true or false
errorReportUrl Custom endpoint to send crash reports to string

Example: Configure crash reporting in app.json

{
  "expo": {
    "errorReports": {
      "enabled": true,
      "endpoint": "https://your-server.com/crash-reports"
    }
  }
}
Note: Crash reports include device info, stack traces, and app state at time of crash.
Warning: Ensure compliance with privacy regulations when collecting crash reports.
Crash Type Description Handled By
JavaScript Exceptions Caught and reported via Expo's error handler Expo.ErrorReport
Native Crashes Crashes in native modules or iOS/Android code Expo.ErrorReport + native crash reporter

11. Using Analytics

Example: Setting up analytics in Expo

import { Analytics } from 'expo-analytics';

const analytics = new Analytics('YOUR_ANALYTICS_ID');

analytics.trackEvent('user_login', {
  userId: '12345',
  timestamp: Date.now(),
});
Property Description Values
trackEvent Tracks a specific event with optional properties string, object
setUserProperties Sets user-specific properties for tracking object
trackPageView Tracks page view events string
Note: Analytics integration requires a valid analytics service ID (e.g., Google Analytics or Mixpanel) to function properly.

12. Tracking Custom Events

Property Description Example
event Name of the custom event to track user_login
properties Object containing additional data about the event { userId: '123', page: 'home' }

Example: Tracking a Custom Event

import { logEvent } from 'expo-analytics';

logEvent('user_login', {
  userId: '123',
  page: 'home'
});
Note: Custom events are tracked using the logEvent function from the expo-analytics package.

Was this article helpful?