禁用后退按钮但是当点击两次退出应用程序时反应本机

Disable back button but when tap twice exit app in react native

我正在尝试创建一个小型 React 本机应用程序,在该应用程序中,我创建了一些屏幕。在特定屏幕上,我想禁用系统后退按钮并且我这样做了,但我想在同一屏幕上创建一个逻辑,如果用户点击两次,则应用程序将关闭。

我的屏幕

import React, {Component, useEffect} from 'react';
import {StyleSheet, Text, View, Button, BackHandler, Alert} from 'react-native';

export default function HomeScreen({navigation}) {
  useEffect(() => {
    BackHandler.addEventListener('hardwareBackPress', () => true);
    return () =>
      BackHandler.removeEventListener('hardwareBackPress', () => true);
  }, []);

  return (
    <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Other Screen"
        onPress={() => navigation.navigate('Employees')}
      />
    </View>
  );
}

但是还有一个问题,这段代码在每个屏幕上都禁用了后退按钮。

对于按两次硬件按钮退出部分,您可以创建一些状态,递增它,当它等于 2 时使用 Backhandler's exitApp function 退出应用程序。

如果您只想为 HomeScreen 组件激活 Backhandler 事件代码,您可以使用 useFocusEffect

React Navigation provides a hook that runs an effect when the screen comes into focus and cleans it up when it goes out of focus

Source

function HomeScreen({navigation}) {
  const [backPressedCount, setBackPressedCount] = useState(0);

  useFocusEffect(
    useCallback(() => {
      BackHandler.addEventListener('hardwareBackPress', () => {
        setBackPressedCount((backPressedCount) => backPressedCount + 1);
        return true;
      });
      return () =>
        BackHandler.removeEventListener('hardwareBackPress', () => true);
    }, []),
  );

  useEffect(() => {
    if (backPressedCount === 2) {
      BackHandler.exitApp();
    }
  }, [backPressedCount]);

  return (
    <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Other Screen"
        onPress={() => navigation.navigate('Employees')}
      />
    </View>
  );
}

基于已接受的答案 (Bas van der Linden)。我创建了这个有用的钩子:

钩子

const usePreventCloseApp = (onBeforeCloseApp) => {
    const [backPressedCount, setBackPressedCount] = useState(0);

    useFocusEffect(
        useCallback(() => {
            const sub = BackHandler.addEventListener(
                'hardwareBackPress',
                () => {
                    if (onBeforeCloseApp) {
                        onBeforeCloseApp(() => setBackPressedCount(2));
                    } else {
                        setBackPressedCount((pre) => {
                            if (pre === 0) {
                                ToastAndroid.show('Press again to exit', 1000);
                                setTimeout(() => setBackPressedCount(0), 1000);
                            }
                            return pre + 1;
                        });
                    }
                    return true;
                },
            );
            return sub.remove;
        }, [onBeforeCloseApp]),
    );

    useEffect(() => {
        if (backPressedCount === 2) {
            BackHandler.exitApp();
        }
    }, [backPressedCount]);

    return {
        closeApp: () => setBackPressedCount(2),
    };
};

用法

显示默认 toast“再次按下退出”

const { closeApp } = usePreventCloseApp();

使用自定义回调

usePreventCloseApp((closeApp) => {
     Alert.alert('Close App', 'Are you sure want to close app?', [
         {
             text: 'Cancel',
             style: 'cancel',
         },
         {
             text: 'Close App',
             style: 'destructive',
             onPress: closeApp,
         },
     ]);
 });