Kartiikeya
Kartiikeya

Reputation: 2516

backAndroid/backHandler working for every screen--React Native

I have enabled backandroid to show logout alert in home screen. Problem is even though screen navigated away from home screen. still Logout alert coming. basic back navigation is also disabled.

HomeScreen.js

 componentWillMount() {
    BackHandler.addEventListener('hardwareBackPress', this._handleback);
}

componentWillUnmount() {
    //Forgetting to remove the listener will cause pop executes multiple times
    BackHandler.removeEventListener('hardwareBackPress', this._handleback);
}

 _handleback = () => {

    Alert.alert(i18N.t('alertHeader'), i18N.t('logoutqHeader'), [
        {
            text: i18N.t('yes'), onPress: () => { this.props.navigation.navigate('login'); }
        },
        { text: i18N.t('cancel'), onPress: () => { return true; }, style: 'cancel' },

    ], { cancelable: false });
    return true;

};

I want to show logout alert only in home screen. In other screens I want to follow basic back navigation. Please let me know how to solve this.

Upvotes: 2

Views: 3746

Answers (6)

Rahul Dasgupta
Rahul Dasgupta

Reputation: 809

Approach #1

import { BackHandler } from 'react-native';

constructor(props) {
    super(props)
    this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}

componentWillMount() {
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}

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

handleBackButtonClick() {
    this.props.navigation.goBack(null);
    return true;
}

But this has an issue, i.e, componentWillMount lifecycle method in React has been deprecated since React version 16.3.0

Hence, Approach #2

componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
    if(this.props.route.name === "login"){
        this.props.navigation.navigate("App Intro");
        return true;
    }
    else{
        this.props.navigation.goBack(null);
        return true;
    } 
}
async componentDidMount(){
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}

Upvotes: 0

ganapati patil
ganapati patil

Reputation: 11

backHandler is applying to all your screen, it's because of using useEffect hook. Let me share my code where I had used useFocusEffect and useCallback method this works fine for me.

useFocusEffect(
    React.useCallback(() => {
      const onBackPress = () => {
       
       Alert.alert('Hold on!', 'Are you sure you want to go back?', [
          {
            text: 'Cancel',
            onPress: () => null,
            style: 'cancel',
          },
          {text: 'YES', onPress: () => navigation.goBack()},
        ]);
        return true;
      };

      BackHandler.addEventListener('hardwareBackPress', onBackPress);

      return () =>
        BackHandler.removeEventListener('hardwareBackPress', onBackPress);
    }, []),
  );

Upvotes: 1

Here is an example implementation:

 componentDidMount() {
    this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBack);   
 }

 componentWillUnmount() {
    this.backHandler.remove();
 }

Upvotes: 0

rohith maddineni
rohith maddineni

Reputation: 11

I just added clean up action in useEffect hook and it worked fine for me

useEffect(() => {
    BackHandler.addEventListener("hardwareBackPress", handleBackButton);
    return () => {
      BackHandler.removeEventListener("hardwareBackPress", handleBackButton);
    };
  }, [])

Upvotes: 1

Kartiikeya
Kartiikeya

Reputation: 2516

Following approach helped me to solve it.

In Homescreen I have included alert normally like in the question.

For the rest of the screens I have included goback() of navigation.

    componentWillMount() {
    BackHandler.addEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}
componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}

It achieved my requirement of showing alert in home screen and going back in other screens with this approach.

Upvotes: 1

simbathesailor
simbathesailor

Reputation: 3687

One solution can be to check for the current screen . in _handleclick add a check for routeName. There can be more solutions, but its difficult to tell by seeing only this amount of code

_handleback = () => {
   //instead of home screen, add your routeName when you are on home screen 
   if(this.props.navigation.state.routeName === "homeScreen")
    Alert.alert(i18N.t('alertHeader'), i18N.t('logoutqHeader'), [
        {
            text: i18N.t('yes'), onPress: () => { this.props.navigation.navigate('login'); }
        },
        { text: i18N.t('cancel'), onPress: () => { return true; }, style: 'cancel' },

    ], { cancelable: false });
    return true;
 }
};

Upvotes: 0

Related Questions