How to handle exit app in one screen not in the whole app - React Native?

10,522

Solution 1

You can check for the screen has been focused prior to call the alert instead of checking the routeName from navigation.

the updated code might look like this.

if (this.props.navigation.isFocused()) {
    Alert.alert(
    "Exit App",
    "Do you want to exit?",
    [
      {
        text: "No",
        onPress: () => console.log("Cancel Pressed"),
        style: "cancel"
      },
      { text: "Yes", onPress: () => BackHandler.exitApp() }
    ],
    { cancelable: false }
    );
}

Solution 2

Version 5+, try using navigation.canGoBack().

I discovered this from Zennichimaro's comment.

If there's only one screen in your stack.

navigation.canGoBack() //=> false

If there's at least one screen below you in the stack.

i.e. If there's a screen that you can go "back" to.

navigation.canGoBack() //=> false

navigation.navigate( "screen2" );

navigation.canGoBack() //=> true

navigation.goBack();

navigation.canGoBack() //=> false
Share:
10,522

Related videos on Youtube

DevAS
Author by

DevAS

Updated on June 04, 2022

Comments

  • DevAS
    DevAS almost 2 years

    I have some issue with BackHandler, the issue is

    when running the app and go to the let's say Sign Up screen and touch the back in my mobile they will run the function and show the Alert to confirm, but now when I go to any other screen and touch the back they will I need to just back to the previous screen on every back BackHandler.exitApp(); runs, Although I write if the routname is SignUp just exit the app not other screens

    this is my code

    Sign Up

        import React from "react";
        import {
          Text,
          TextInput,
          ActivityIndicator,
          View,
          KeyboardAvoidingView,
          ScrollView,
          Image,
          TouchableOpacity,
          BackHandler,
          Alert
        } from "react-native";
        export default class signUp extends React.Component {
          constructor(props) {
            super(props);
    
          }
    
          componentDidMount() {
            BackHandler.addEventListener("hardwareBackPress", this.backPressed);
          }
    
          componentWillUnmount() {
            BackHandler.removeEventListener("hardwareBackPress", this.backPressed);
          }
          backPressed = () => {
        let { routeName } = this.props.navigation.state;
        console.log("route is :  " + routeName);
    
        if (routeName == "SignUp") {
          console.log("ROUTE :  " + routeName);
          Alert.alert(
            "Exit App",
            "Do you want to exit?",
            [
              {
                text: "No",
                onPress: () => console.log("Cancel Pressed"),
                style: "cancel"
              },
              { text: "Yes", onPress: () => BackHandler.exitApp() }
            ],
            { cancelable: false }
          );
          return true;
        } else {
          return false;
        }
      };
    
          render() {....}
        }
    

    Routes

    import { createStackNavigator, createAppContainer } from "react-navigation";
    import React from "react";
    import { View } from "react-native";
    import Splash from "../screens/Splash";
    import Home from "../screens/Home";
    import SignUp from "../screens/SignUp";
    import SignIn from "../screens/SignIn";
    import ForgetPassword from "../screens/ForgetPassword";
    
    const Routes = createStackNavigator(
      {
        Splash: {
          screen: Splash,
          navigationOptions: {
            header: null
          }
        },
        SignUp: {
          screen: SignUp,
          navigationOptions: () => ({
            // header: null
            title: "Sign Up",
            headerLeft: null,
            headerTintColor: "#fc0301",
            headerStyle: {
              borderBottomColor: "white"
            },
            headerTitleStyle: {
              color: "#fc0301",
              textAlign: "center",
              flex: 1,
              elevation: 0,
              fontSize: 25,
              justifyContent: "center"
            }
          })
        },
        SignIn: {
          screen: SignIn,
          navigationOptions: {
            title: "Sign In",
            headerRight: <View />,
            headerTintColor: "#fc0301",
            headerStyle: {
              borderBottomColor: "white"
            },
            headerTitleStyle: {
              color: "#fc0301",
              textAlign: "center",
              flex: 1,
              elevation: 0,
              fontSize: 25,
              justifyContent: "center"
            }
          }
        },
        ForgetPassword: {
          screen: ForgetPassword,
          navigationOptions: {
            header: null
          }
        },
        Home: {
          screen: Home,
          navigationOptions: {
            header: null
          }
        }
      },
      {
        initialRouteName: "Splash"
      }
    );
    
    export default createAppContainer(Routes);
    
    • Hend El-Sahli
      Hend El-Sahli
      Your issue here could be solved by using a SwitchNavigator that would render: 1. Splash screen. 2. Your StackNavigator once you're directed to your stack, the backButton will never take you back to your Splash screen
  • DevAS
    DevAS about 5 years
    sadly didn't work :/ in every screen I show the Alert
  • DevAS
    DevAS about 5 years
    I write your code just add case "SignIn" alert"something" to test them in the Sign In screen
  • DevAS
    DevAS about 5 years
    I made some magic I don't know why it's work :D i just replace routeName with this.props.navigation.isFocused() and it's work finally !!
  • DevAS
    DevAS about 5 years
    yes, that's work, If I need to run the alert in the many screens I need to call this function in every screen? for example, I wanna run the alert in SignUp and "Home" and some other!
  • Mukundhan
    Mukundhan about 5 years
    If you have specific screens that needs this functionality, you can use it in a common service class and call it on componentDidMount. so that it will be easy to maintain.
  • Oliver D
    Oliver D about 4 years
    How can i handle it in react-navigation V5
  • Zennichimaro
    Zennichimaro over 3 years
    seems like it is no longer the case in v5, navigation.isFocused() always returns true and worse is navigation.canGoBack() always returns false, I have no idea how to know when I am on top most of the stack and really can't go back anymore
  • Mukundhan
    Mukundhan over 3 years
    have you tried using a counter redux action, we have used global counter before finding this solution. it will always work!
  • Joshua Pinter
    Joshua Pinter over 2 years
    @Zennichimaro I'm on version 5 and from my tests, navigation.canGoBack() is working well. It shows false when you're at the root of the stack and shows true when I'm nested down at least 1 screen in the stack. Not sure how your finding this or maybe they've updated it since you tried it. I'm on "@react-navigation/native": "5.9.8", "@react-navigation/stack": "5.14.9"