npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ibrahim-rahhal/expo-exit-app

v1.0.0

Published

A React Native package for gracefully exiting Expo applications

Readme

@ibrahim-rahhal/expo-exit-app

A React Native package for gracefully exiting Expo applications with multiple fallback strategies.

npm version License: MIT

🚀 Features

  • Multiple Exit Strategies: BackHandler, Updates reload, and force crash
  • Graceful Fallbacks: Automatically tries multiple methods
  • TypeScript Support: Fully typed for better development experience
  • React Hooks: Easy integration with React components
  • Platform Detection: Automatically detects available exit methods
  • Customizable: Configure error messages, delays, and strategies

📦 Installation

npm install @ibrahim-rahhal/expo-exit-app

or

yarn add @ibrahim-rahhal/expo-exit-app

🔧 Basic Usage

Using the Hook (Recommended)

import React from 'react';
import { View, Button, Alert } from 'react-native';
import { useExitApp } from '@ibrahim-rahhal/expo-exit-app';

export default function App() {
  const { exit } = useExitApp();

  const handleExit = () => {
    Alert.alert(
      'Exit App',
      'Are you sure you want to exit?',
      [
        { text: 'Cancel', style: 'cancel' },
        {
          text: 'Exit',
          onPress: async () => {
            const result = await exit({
              errorMessage: 'User requested app exit',
            });
            console.log('Exit result:', result);
          },
        },
      ]
    );
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button title="Exit App" onPress={handleExit} />
    </View>
  );
}

Using the Class Directly

import { ExitApp, ExitStrategy } from '@ibrahim-rahhal/expo-exit-app';

// Simple exit with default options
await ExitApp.exit();

// Exit with custom options
await ExitApp.exit({
  errorMessage: 'Custom exit message',
  useReload: true,
  forceDelay: 200,
});

// Exit with specific strategy
await ExitApp.exitWithStrategy(ExitStrategy.BACK_HANDLER);

📚 API Reference

useExitApp() Hook

Returns an object with the following methods:

const {
  exit,
  exitWithStrategy,
  isBackHandlerSupported,
  isReloadSupported,
  getSupportedStrategies,
} = useExitApp();

Methods

  • exit(options?): Exit using graceful strategy with fallbacks
  • exitWithStrategy(strategy, options?): Exit using a specific strategy
  • isBackHandlerSupported(): Check if BackHandler.exitApp() is available
  • isReloadSupported(): Check if Updates.reloadAsync() is available
  • getSupportedStrategies(): Get array of supported exit strategies

ExitApp Class

Static methods for app termination:

ExitApp.exit(options?): Promise<ExitResult>

Gracefully exit the app using multiple fallback strategies.

ExitApp.exitWithStrategy(strategy, options?): Promise<ExitResult>

Exit using a specific strategy.

Platform Detection Methods

  • ExitApp.isBackHandlerSupported(): boolean
  • ExitApp.isReloadSupported(): boolean
  • ExitApp.getSupportedStrategies(): ExitStrategy[]

Types

ExitOptions

interface ExitOptions {
  /** Custom error message to use when forcing app termination */
  errorMessage?: string;
  /** Whether to try Updates.reloadAsync() first (default: true) */
  useReload?: boolean;
  /** Delay in milliseconds before attempting force termination (default: 100) */
  forceDelay?: number;
}

ExitStrategy

enum ExitStrategy {
  BACK_HANDLER = 'backHandler',    // Use BackHandler.exitApp()
  RELOAD = 'reload',               // Use Updates.reloadAsync()
  FORCE_CRASH = 'forceCrash',      // Force crash with unhandled error
  GRACEFUL = 'graceful',           // Try all strategies with fallbacks
}

ExitResult

interface ExitResult {
  /** Whether the exit attempt was successful */
  success: boolean;
  /** The strategy that was used */
  strategy: ExitStrategy;
  /** Error message if the exit failed */
  error?: string;
}

🎯 Exit Strategies

1. Graceful (Default)

Tries multiple strategies in order:

  1. Updates.reloadAsync() (if enabled and useReload: true)
  2. BackHandler.exitApp() (if available)
  3. Force crash with unhandled error

2. BackHandler

Uses BackHandler.exitApp() - works primarily on Android.

3. Reload

Uses Updates.reloadAsync() to reload the app, effectively restarting it.

4. Force Crash

Forces an unhandled error to crash the app. Uses ErrorUtils.reportFatalError() if available, otherwise throws an error.

🔍 Advanced Examples

Custom Exit Flow

import { useExitApp, ExitStrategy } from '@ibrahim-rahhal/expo-exit-app';

export function useCustomExit() {
  const { exitWithStrategy, getSupportedStrategies } = useExitApp();

  const customExit = async () => {
    const strategies = getSupportedStrategies();
    
    // Try BackHandler first if available
    if (strategies.includes(ExitStrategy.BACK_HANDLER)) {
      const result = await exitWithStrategy(ExitStrategy.BACK_HANDLER);
      if (result.success) return result;
    }

    // Fallback to force crash
    return exitWithStrategy(ExitStrategy.FORCE_CRASH, {
      errorMessage: 'Custom exit flow terminated app',
      forceDelay: 500,
    });
  };

  return { customExit };
}

Region Check Example (Based on Your Code)

import React, { useEffect } from 'react';
import { Alert } from 'react-native';
import { useExitApp } from '@ibrahim-rahhal/expo-exit-app';

export function RegionCheck() {
  const { exit } = useExitApp();

  useEffect(() => {
    const timer = setTimeout(() => {
      Alert.alert(
        'Region Not Supported',
        "Your region isn't supported",
        [
          {
            text: 'OK',
            onPress: async () => {
              await exit({
                errorMessage: 'App terminated due to unsupported region',
                useReload: true,
                forceDelay: 100,
              });
            },
          },
        ],
        { cancelable: false }
      );
    }, 3000);

    return () => clearTimeout(timer);
  }, [exit]);

  return null; // This is just a utility component
}

🛠️ Platform Support

| Platform | BackHandler | Updates Reload | Force Crash | |----------|-------------|----------------|-------------| | Android | ✅ | ✅ | ✅ | | iOS | ❌ | ✅ | ✅ | | Web | ❌ | ✅ | ✅ |

Note: iOS doesn't allow apps to programmatically exit, but force crash will work for development/testing.

⚠️ Important Notes

  1. iOS Behavior: Apple doesn't allow apps to programmatically exit on iOS. The force crash method is mainly for development/testing purposes.

  2. Production Use: Be careful when using force crash in production apps, as it may affect crash reporting and user experience.

  3. Updates.reloadAsync(): Only works when Expo Updates is enabled and configured.

  4. Testing: Test thoroughly on your target platforms, as behavior may vary.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

👨‍💻 Author

Ibrahim Rahhal - @Ibrahimrahhal

🙏 Acknowledgments

  • Inspired by react-native-exit-app
  • Built for the Expo ecosystem
  • Thanks to the React Native and Expo communities