Skip to content

liujigang/react-native-error-handler

react-native-error-handler

中文文档 | English

A library for handling React Native errors, providing error boundary and global error handling functionality.

Features

  • 🛡️ Error Boundary: Catch JavaScript errors in React component tree
  • 🌐 Global Error Handling: Catch unhandled JavaScript errors and Promise rejections
  • 🔧 Promise Patching: Resolve React Native Promise version mismatch issues
  • 📱 Cross-platform Support: Support for iOS and Android platforms
  • 🎨 Custom Error Pages: Support for custom error fallback components
  • 📊 Detailed Error Information: Provide error stack, timestamp, platform info and other context

Project Structure

src/
├── components/
│   └── ErrorBoundary/           # Error boundary component
│       ├── DefaultFallback/     # Default error fallback component
│       │   ├── index.tsx        # Component implementation
│       │   └── styles.ts        # Style definitions
│       └── index.tsx            # Main error boundary component
├── handlers/                    # Error handlers
│   ├── setupErrorUtilsGlobalHandler.ts      # Global error handler
│   └── setupUnhandledRejectionsTracking.ts  # Unhandled rejection tracking
├── types/
│   └── index.ts                 # TypeScript type definitions
├── utils/                       # Utility functions
│   ├── environment.ts           # Environment detection
│   ├── error.ts                 # Error handling utilities
│   ├── promisePolyfill.ts       # Promise patching
│   ├── setupReactNativeErrorHandlers.ts  # Main setup function
│   └── toolkit.ts               # Common utilities
├── __tests__/                   # Test files
│   └── index.test.tsx
└── index.tsx                    # Main entry file

Installation

# npm
npm install react-native-error-handler

# yarn
yarn add react-native-error-handler

Usage

Basic Usage

1. Error Boundary

Error boundaries are used to catch JavaScript errors in React component tree, preventing the entire app from crashing.

import React from 'react';
import { ErrorBoundary } from 'react-native-error-handler';

// Custom error fallback component
const CustomFallback = ({ resetError }) => (
  <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text>An error occurred, please try again</Text>
    <Button title="Retry" onPress={resetError} />
  </View>
);

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={CustomFallback}
      onError={(errorInfo) => {
        console.log('Error caught:', errorInfo);
        // You can report errors to error monitoring services here
        // reportError(errorInfo);
      }}
    >
      <YourAppComponents />
    </ErrorBoundary>
  );
}

2. Global Error Handling

Set up global error handlers to catch unhandled JavaScript errors and Promise rejections.

import { setupReactNativeErrorHandlers } from 'react-native-error-handler';

// Set up global error handling at app startup
setupReactNativeErrorHandlers(
  {
    enableGlobalErrorHandler: true,    // Enable global error handling
    enableUnhandledRejection: true,   // Enable unhandled Promise rejection handling
    patchGlobalPromise: true,         // Patch global Promise
    enableInDev: true,                // Enable in development mode
  },
  (errorInfo) => {
    console.log('Global error:', errorInfo);
    // Report errors to error monitoring services
    // reportError(errorInfo);
  }
);

Complete Example

import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import {
  ErrorBoundary,
  setupReactNativeErrorHandlers
} from 'react-native-error-handler';

// Custom error fallback component
const CustomErrorFallback = ({ resetError }) => (
  <View style={styles.errorContainer}>
    <Text style={styles.errorTitle}>Application Error</Text>
    <Text style={styles.errorMessage}>
      Sorry, the application encountered a problem. Please click the retry button to reload.
    </Text>
    <Button title="Retry" onPress={resetError} />
  </View>
);

// Set up global error handling
setupReactNativeErrorHandlers(
  {
    enableGlobalErrorHandler: true,
    enableUnhandledRejection: true,
    patchGlobalPromise: true,
    enableInDev: true,
  },
  (errorInfo) => {
    console.error('Global error caught:', errorInfo);

    // Error information includes the following fields:
    // - error: Error object
    // - isFatal: Whether it's a fatal error
    // - type: Error type ('error' | 'unhandledrejection')
    // - timestamp: Error occurrence timestamp
    // - context: Additional context information (platform, stack, etc.)

    // You can report errors to error monitoring services here
    // reportError(errorInfo);
  }
);

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={CustomErrorFallback}
      onError={(errorInfo) => {
        console.error('Component error caught:', errorInfo);
        // Handle component-level errors
      }}
    >
      <View style={styles.container}>
        <Text>Your app content</Text>
        {/* Your app components */}
      </View>
    </ErrorBoundary>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  errorTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  errorMessage: {
    fontSize: 14,
    textAlign: 'center',
    marginBottom: 20,
  },
});

Configuration Options

ErrorHandlerOptions

interface ErrorHandlerOptions {
  /** Whether to enable global error handling */
  enableGlobalErrorHandler?: boolean;
  /** Whether to enable unhandled Promise rejection handling */
  enableUnhandledRejection?: boolean;
  /** Whether to enable in development mode */
  enableInDev?: boolean;
  /** Whether to patch global Promise (to resolve React Native Promise version mismatch issues) */
  patchGlobalPromise?: boolean;
}

ErrorInfo

interface ErrorInfo {
  /** Error object */
  error: Error;
  /** Whether it's a fatal error */
  isFatal?: boolean;
  /** Error type */
  type: 'error' | 'unhandledrejection';
  /** Error occurrence timestamp */
  timestamp: number;
  /** Additional context information */
  context?: Record<string, any>;
}

Usage Guidelines

Best Practices

  1. Use ErrorBoundary at the root component

    // In App.js or index.js
    <ErrorBoundary onError={handleError}>
      <App />
    </ErrorBoundary>
  2. Set up global error handling at app startup

    // At the top of index.js or App.js
    import { setupReactNativeErrorHandlers } from 'react-native-error-handler';
    
    setupReactNativeErrorHandlers(
      { enableGlobalErrorHandler: true, enableUnhandledRejection: true },
      (errorInfo) => {
        // Report errors to monitoring system
      }
    );
  3. Error reporting integration

    const reportError = (errorInfo) => {
      // Send to error monitoring services (e.g., Bugsnag, Firebase Crashlytics, etc.)
      // Example: Using Sentry
      // Sentry.captureException(errorInfo.error, {
      //   extra: {
      //     isFatal: errorInfo.isFatal,
      //     type: errorInfo.type,
      //     timestamp: errorInfo.timestamp,
      //     context: errorInfo.context,
      //   }
      // });
    
      // Example: Report to custom monitoring service
      fetch('/api/errors', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          error: errorInfo.error.message,
          stack: errorInfo.error.stack,
          isFatal: errorInfo.isFatal,
          type: errorInfo.type,
          timestamp: errorInfo.timestamp,
          context: errorInfo.context,
        }),
      });
    };

Important Notes

  • Development Environment: By default, global error handling is disabled in development mode, can be enabled with enableInDev: true
  • Promise Patching: If you encounter Promise-related issues, it's recommended to enable patchGlobalPromise: true
  • Error Boundary Limitations: Error boundaries can only catch errors in child component trees, cannot catch the following errors:
    • Errors in event handlers
    • Errors in asynchronous code (such as setTimeout, Promise)
    • Errors during server-side rendering
    • Errors in the error boundary itself

Troubleshooting

Common Issues

  1. Error boundary not working

    • Ensure ErrorBoundary wraps components that might throw errors
    • Check if the component is imported correctly
  2. Global error handling not effective

    • Ensure setupReactNativeErrorHandlers is called early in app startup
    • Check if configuration options are set correctly
  3. Promise-related errors

    • Enable patchGlobalPromise: true option
    • Check React Native version compatibility

API Reference

ErrorBoundary Props

Property Type Required Description
onError (errorInfo: ErrorInfo) => void No Error callback function
FallbackComponent ComponentType<{ resetError: () => void }> No Custom error fallback component

setupReactNativeErrorHandlers Parameters

Parameter Type Default Description
options.enableGlobalErrorHandler boolean true Enable global error handling
options.enableUnhandledRejection boolean true Enable unhandled Promise rejection handling
options.enableInDev boolean true Enable in development mode
options.patchGlobalPromise boolean true Patch global Promise
callback ErrorCallback - Error callback function

Contributing

License

MIT


Made with create-react-native-library

Some code comes from sentry-react-native

Some code comes from es-toolkit

About

handler react-native error

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published