React native 后退按钮反应本机退出应用程序

React native 后退按钮反应本机退出应用程序,react-native,react-native-android,React Native,React Native Android,我已经在我的主屏幕上的react native应用程序中设置了android后退按钮退出应用程序功能。但当我在其他屏幕上按下android后退按钮时,它也会被调用 componentDidMount() { if (Platform.OS == "android") { BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);

我已经在我的主屏幕上的react native应用程序中设置了android后退按钮退出应用程序功能。但当我在其他屏幕上按下android后退按钮时,它也会被调用

componentDidMount() {

    if (Platform.OS == "android") {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);                           
  }
    this._setupGoogleSignin();           
    this._getUserDetails();
    const { navigate } = this.props.navigation;
    console.log("object url is", this.state.postsArray[0].url);

}

handleBackButton = () => {               
    Alert.alert(
        'Exit App',
        'Exiting the application?', [{
            text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel'
        }, {
            text: 'OK',
            onPress: () => BackHandler.exitApp()
        }, ], {
            cancelable: false
        }
     )
     return true;
   }
componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  }

如果在导航到其他屏幕时,或在卸载
主屏幕时,主屏幕仍处于安装状态,如果不删除EventListener,则仍将调用它

您应该在导航或卸载时清除EventListener

onButtonPress = () => {
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  // then navigate
  navigate('NewScreen');
}

handleBackButton = () => {
 Alert.alert(
     'Exit App',
     'Exiting the application?', [{
         text: 'Cancel',
         onPress: () = > console.log('Cancel Pressed'),
         style: 'cancel'
     }, {
         text: 'OK',
         onPress: () = > BackHandler.exitApp()
     }, ], {
         cancelable: false
     }
  )
  return true;
} 

componentDidMount() {
  BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}

Guyz请理解这可能不仅仅是react native的问题。与firebase集成时要小心。最近的firebase版本存在在react原生应用程序中集成后退按钮的问题!!请将firebase版本降级为firebase版本@5.0.3,然后重新检查是否工作!我也有同样的问题,担心了好几天。我最终降级到@5.0.3版本,现在后退按钮工作得非常好!如果仍然面临此问题,您可能会降级到较低版本。

我们可以在主应用程序容器中为didfocus添加订阅。我们可以添加逻辑以检查是否有使用静态变量点击的按钮

import {  Alert,  BackHandler,  ToastAndroid } from 'react-native';
import {  StackActions } from 'react-navigation';
import { Toast } from 'native-base';
// common statless class variable.
let backHandlerClickCount = 0;

class App extends React.Component {
    constructor(props) {
      super(props);
      // add listener to didFocus
      this._didFocusSubscription = props.navigation.addListener('didFocus', payload =>
        BackHandler.addEventListener('hardwareBackPress', () => this.onBackButtonPressAndroid(payload)));
    }

    // remove listener on unmount 
    componentWillUnmount() {
      if (this._didFocusSubscription) {
        this._didFocusSubscription.remove();
      }
    }

    onBackButtonPressAndroid = () => {
      const shortToast = message => {
        // ToastAndroid.showWithGravityAndOffset(
        //     message,
        //     ToastAndroid.SHORT,
        //     ToastAndroid.BOTTOM,
        //     25,
        //     50
        // );

        // ios & android
        Toast.show({
            text: message,
            type: 'warning',
            position: 'top',
            duration: 3000,
        });
        }

        const {
          clickedPosition
        } = this.state;
        backHandlerClickCount += 1;
        if ((clickedPosition !== 1)) {
          if ((backHandlerClickCount < 2)) {
            shortToast('Press again to quit the application!');
          } else {
            BackHandler.exitApp();
          }
        }

        // timeout for fade and exit
        setTimeout(() => {
          backHandlerClickCount = 0;
        }, 2000);

        if (((clickedPosition === 1) &&
            (this.props.navigation.isFocused()))) {
          Alert.alert(
            'Exit Application',
            'Do you want to quit application?', [{
              text: 'Cancel',
              onPress: () => console.log('Cancel Pressed'),
              style: 'cancel'
            }, {
              text: 'OK',
              onPress: () => BackHandler.exitApp()
            }], {
              cancelable: false
            }
          );
        } else {
          this.props.navigation.dispatch(StackActions.pop({
            n: 1
          }));
        }
        return true;
      }

    }
从'react native'导入{Alert,BackHandler,ToastAndroid};
从“react navigation”导入{StackActions};
从'native base'导入{Toast};
//公共无状态类变量。
让backHandlerClickCount=0;
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
//将侦听器添加到didFocus
这是._didFocusSubscription=props.navigation.addListener('didFocus',payload=>
BackHandler.addEventListener('hardwareBackPress',()=>this.onBackButtonPressAndroid(有效负载));
}
//卸载时删除侦听器
组件将卸载(){
如果(这是一项重点认购){
此._didFocusSubscription.remove();
}
}
onBackButtonPressAndroid=()=>{
const shortToast=消息=>{
//用重力和偏移量来显示(
//信息,
//ToastAndroid.SHORT,
//ToastAndroid.BOTTOM,
//     25,
//     50
// );
//ios和android
吐司,表演({
文本:消息,
键入:“警告”,
位置:'顶部',
时长:3000,
});
}
常数{
点击位置
}=本州;
backHandlerClickCount+=1;
如果((单击位置!==1)){
如果((backHandlerClickCount<2)){
shortToast('再次按退出应用程序!');
}否则{
BackHandler.exitApp();
}
}
//淡入淡出超时
设置超时(()=>{
backHandlerClickCount=0;
}, 2000);
如果((单击位置===1)&&
(this.props.navigation.isFocused())){
警惕,警惕(
“退出应用程序”,
'是否要退出应用程序?'[{
文本:“取消”,
onPress:()=>console.log('Cancel Pressed'),
样式:“取消”
}, {
文本:“OK”,
onPress:()=>BackHandler.exitApp()
}], {
可取消:false
}
);
}否则{
this.props.navigation.dispatch(StackActions.pop({
n:1
}));
}
返回true;
}
}

如果您不希望警报消息出现在其他组件/屏幕中,而只出现在一个特定组件/屏幕中,您可以按照此操作

import { withNavigationFocus } from 'react-navigation';

class TestComponent extends Component {
  componentWillMount() {
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  }

  handleBackButton = () => {
    if (this.props.isFocused) {
      Alert.alert(
        'Exit App',
        'Exiting the application?',
        [
          {
            text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel'
          },
          {
            text: 'OK',
            onPress: () => BackHandler.exitApp()
          }
        ],
        {
          cancelable: false
        }
      );
      return true;
    }
  };
} 

export default withNavigationFocus(TestComponent );

显示警报消息的BackHandler将仅在TestComponent中工作

您始终可以动态修改
BackHandler.addEventListener
的回调函数基于当前场景的内容(使用
react native router flux
可以轻松实现)


完整的要点可以在这里找到:

如果你想双击返回按钮退出应用程序

import React, {useEffect} from 'react';
import {BackHandler} from 'react-native';
import {Provider} from 'react-redux';
import Toast from 'react-native-root-toast';

let backHandlerClickCount = 0;

const App = () => {
    useEffect(() => {
        // back handle exit app
        BackHandler.addEventListener('hardwareBackPress', backButtonHandler);
        return () => {
            BackHandler.removeEventListener('hardwareBackPress', backButtonHandler);
        };
    }, []);
    const backButtonHandler = () => {
        const shortToast = message => {
            Toast.show(message, {
                duration: Toast.durations.LONG,
                position: Toast.positions.BOTTOM,
            });
        }
        let backHandlerClickCount;
        backHandlerClickCount += 1;
        if ((backHandlerClickCount < 2)) {
            shortToast('Press again to quit the application');
        } else {
            BackHandler.exitApp();
        }

        // timeout for fade and exit
        setTimeout(() => {
            backHandlerClickCount = 0;
        }, 1000);
        
        return true;
    }
    return (
        <Provider store={store}>
         ....
        </Provider>
    );
};

export default App;
import React,{useffect}来自“React”;
从“react native”导入{BackHandler};
从'react redux'导入{Provider};
从“react native root Toast”导入Toast;
让backHandlerClickCount=0;
常量应用=()=>{
useffect(()=>{
//后把手退出应用程序
addEventListener('hardwareBackPress',backButtonHandler);
return()=>{
removeEventListener('hardwareBackPress',backButtonHandler);
};
}, []);
常量backButtonHandler=()=>{
const shortToast=消息=>{
祝酒词{
持续时间:Toast.durations.LONG,
位置:Toast.positions.BOTTOM,
});
}
让BackHandler点击计数;
backHandlerClickCount+=1;
如果((backHandlerClickCount<2)){
shortToast('再次按退出应用程序');
}否则{
BackHandler.exitApp();
}
//淡入淡出超时
设置超时(()=>{
backHandlerClickCount=0;
}, 1000);
返回true;
}
返回(
....
);
};
导出默认应用程序;

只是添加到其他答案中

如果您使用的是
“@react navigation/native”
,则在backButton上设置eventListner将起作用,即使您已导航到子屏幕。要克服此问题,请将eventListner设置在
焦点
上,而不是使用
componentDidMount()
并在屏幕上发生
模糊
事件时将其删除


}

我在这个问题上也遇到了问题,但我设法用一种非常简单的方法解决了它。我使用的是react导航4.4.1

import React from 'react';
import { BackHandler, ToastAndroid} from 'react-native';

export default class LoginScreen extends React.Component {

    state = {
        canBeClosed: false
    }

    componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    }
      
    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
    }

    handleBackButton = () => {
        if (this.props.navigation.isFocused()) {
            if (this.state.canBeClosed)
                return this.state.canBeClosed = false;
    
            else {
                setTimeout(() => { this.state.canBeClosed = false }, 3000);    
                ToastAndroid.show("Press Again To Exit !", ToastAndroid.SHORT);
    
                return this.state.canBeClosed = true
            }   
        }
    };

 //some code

}

@请用您尝试过的代码更新您的问题。主屏幕是我打开应用程序时打开的主屏幕。所以我想在点击硬件后退按钮时退出应用程序。我已经更新了code@ParasWatts正如我在回答中所说的,我相信主屏幕并没有卸载
import React, {useEffect} from 'react';
import {BackHandler} from 'react-native';
import {Provider} from 'react-redux';
import Toast from 'react-native-root-toast';

let backHandlerClickCount = 0;

const App = () => {
    useEffect(() => {
        // back handle exit app
        BackHandler.addEventListener('hardwareBackPress', backButtonHandler);
        return () => {
            BackHandler.removeEventListener('hardwareBackPress', backButtonHandler);
        };
    }, []);
    const backButtonHandler = () => {
        const shortToast = message => {
            Toast.show(message, {
                duration: Toast.durations.LONG,
                position: Toast.positions.BOTTOM,
            });
        }
        let backHandlerClickCount;
        backHandlerClickCount += 1;
        if ((backHandlerClickCount < 2)) {
            shortToast('Press again to quit the application');
        } else {
            BackHandler.exitApp();
        }

        // timeout for fade and exit
        setTimeout(() => {
            backHandlerClickCount = 0;
        }, 1000);
        
        return true;
    }
    return (
        <Provider store={store}>
         ....
        </Provider>
    );
};

export default App;
export class sampleScreen extends Component {
constructor(props) {
    super(props);
    this.state = {
        foo: '',
        bar: '',
    };

    this._unsubscribeSiFocus = this.props.navigation.addListener('focus', e => {
        console.warn('focus signIn');
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    });
    this._unsubscribeSiBlur = this.props.navigation.addListener('blur', e => {
        console.warn('blur signIn');
        BackHandler.removeEventListener(
            'hardwareBackPress',
            this.handleBackButton,
        );
    });

    onButtonPress = () => {
        BackHandler.removeEventListener(
            'hardwareBackPress',
            this.handleBackButton,
        );
    };
}

handleBackButton = () => {
    Alert.alert(
        'Exit App',
        'Exiting the application?',
        [{
                text: 'Cancel',
                onPress: () => console.log('Cancel Pressed'),
                style: 'cancel',
            },
            {
                text: 'OK',
                onPress: () => BackHandler.exitApp(),
            },
        ], {
            cancelable: false,
        },
    );
    return true;
};

componentDidMount() {
    // BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
    this._unsubscribeSiFocus();
    this._unsubscribeSiBlur();
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
import React from 'react';
import { BackHandler, ToastAndroid} from 'react-native';

export default class LoginScreen extends React.Component {

    state = {
        canBeClosed: false
    }

    componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    }
      
    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
    }

    handleBackButton = () => {
        if (this.props.navigation.isFocused()) {
            if (this.state.canBeClosed)
                return this.state.canBeClosed = false;
    
            else {
                setTimeout(() => { this.state.canBeClosed = false }, 3000);    
                ToastAndroid.show("Press Again To Exit !", ToastAndroid.SHORT);
    
                return this.state.canBeClosed = true
            }   
        }
    };

 //some code

}