3

on Android Mi Note 3, hardware back button is not fire the handleBackPress , when I will click on back the app exit.

I have do the following code but the handleBackPress is not called.

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

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

  handleBackPress = () => {
    this.goBack(); // works best when the goBack is async
    return true;
  }

Navigation Code :

const ModalSignUp = createStackNavigator(
  {
    Signup: { screen: Signup, key: 'Signup' },
    PartyList: { screen: PartyList, key: 'PartyList' },
    StatesList: { screen: StatesList, key: 'StatesList' },

  },
  {
    initialRouteName: 'Signup',
    headerMode: 'none',
    mode: 'card',
  }
);

Navigate :

this.props.navigation.push("StatesList")

Expected :

back click on hardware button, go to previous screen.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Kirit Modi
  • 23,155
  • 15
  • 89
  • 112

5 Answers5

3

Your error can be in the way you get the next view of react-navigation.

You need to use .push to create a new view on the stack and when you click the back button, the .goBack() will be triggered.

By default, back button will always make the navigation to go back on the stack, but if you have only one view in the stack (this happens when you only use .navigate) the app will exit.

Not sure how you are navigating through the views, but this can be a solution.

Edit: To solve this problem, when navigating through views, use navigation.push('viewname') instead of navigation.navigate('viewname'). You don't need any other method (like the one you put in the question).

Also check the docs to understand the how navigating works or this question

Pavel Lint
  • 3,252
  • 1
  • 18
  • 18
Vencovsky
  • 28,550
  • 17
  • 109
  • 176
2

Try using return false instead of return true.

Piyush Govil
  • 358
  • 3
  • 13
1

1. Import

import { BackHandler, DeviceEventEmitter } from 'react-native'

2. constructor

constructor(props) {
    super(props)
    this.backPressSubscriptions = new Set()
  }

3. Add and Remove Listeners

componentDidMount() {
    DeviceEventEmitter.removeAllListeners('hardwareBackPress')
    DeviceEventEmitter.addListener('hardwareBackPress', () => {
        let invokeDefault = true
        const subscriptions = []

        this.backPressSubscriptions.forEach(sub => subscriptions.push(sub))

        for (let i = 0; i < subscriptions.reverse().length; i += 1) {
            if (subscriptions[i]()) {
                invokeDefault = false
                break
            }
        }

        if (invokeDefault) {
            BackHandler.exitApp()
        }
    })

    this.backPressSubscriptions.add(this.handleHardwareBack)
}

componentWillUnmount() {
    DeviceEventEmitter.removeAllListeners('hardwareBackPress')
    this.backPressSubscriptions.clear()
}

4. Handle back

handleHardwareBack = () => {
    this.props.navigation.goBack(null)
    console.log(" ********** This is called ************ ");
    return true;
}
Kirit Modi
  • 23,155
  • 15
  • 89
  • 112
  • I don't think that you need to do this if you use `.push()` in all of your views. I have an app that use `react-navigation` and it works as you want without doing this. You said it happens in all devices, but i think is something only on specific devices. – Vencovsky Mar 18 '19 at 14:44
0

Try this:

import {BackHandler} from 'react-native';

export default class Component extends Component {
     _didFocusSubscription;
     _willBlurSubscription;
     constructor(props) {
         super(props);
         this._didFocusSubscription = props.navigation.addListener('didFocus',payload =>
            BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
         ); 
     }
  }
componentDidMount() {
        this._willBlurSubscription = this.props.navigation.addListener('willBlur', payload =>
            BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
        );
 }
componentWillUnmount() {
        this._didFocusSubscription && this._didFocusSubscription.remove();
        this._willBlurSubscription && this._willBlurSubscription.remove();
    }
onBackButtonPressAndroid = () => {
    //code when you press the back button
 };
MPN7
  • 1,112
  • 1
  • 10
  • 13
0

Give it a try... this one works for me: in componentWillUnmount

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

Also, make sure in each case you check in your this.goBack(); it return something

goback = () => {
   if (condition2) 
     // handling
    return something;

  if (condition2)
   // handling
   return something;

  // default:
  return true;
};
Hend El-Sahli
  • 6,268
  • 2
  • 25
  • 42