Rakib
Rakib

Reputation: 7625

Back button handler does not get invoked react native

I am facing this weired issue with android back button handler. Consider I have 3 screens, A, B, and C. I am using stack navigator. A navigates to B, which navigates to C.

I want to be able to go back from C to B, but not from B to A. For this, in B, I do this:

async componentDidMount() {
    if (Platform.OS === "android") {
      BackHandler.addEventListener(
        "hardwareBackPress",
        this.onBackButtonPressAndroid.bind(this)
      );
    }
 }
 
 onBackButtonPressAndroid = () => {
    Alert.alert("Backed"); //this is just to test
    return true; //make it true to prevent going back
  };

And in C:

 if (Platform.OS === "android") {
      BackHandler.addEventListener(
        "hardwareBackPress",
        this.onBackButtonPressAndroid.bind(this)
      );
    }

onBackButtonPressAndroid = () => {
    this.props.navigation.goBack(null);
    return true;
  };

I have removed the event listener in componentWillUnmount.

When I go from A to B, and press back button, it behaves correctly: it does not go back to A, and I see the alert.

But then when I go from B to C, then combe back to B (using back button), if I again press back button, it goes back to A and I don't see the alert.

Why is that happening?

Update If I don not set the event handler in C, then when I press back button, I see the alert! that means the handlers in B gets called!

Upvotes: 0

Views: 885

Answers (1)

Zaytri
Zaytri

Reputation: 2574

Add/remove the event listener based on the navigation lifecycle, rather than the component lifecycle. The event listener should not be necessary in C.

import React from 'react'
import { Alert, Platform } from 'react-native'
import { NavigationEvents } from 'react-navigation'

export default class YourComponent extends React.Component {
  onBackPressAndroid = () => {
    Alert.alert('Cannot go back')
    return true
  }

  didFocus = () => BackHandler.addEventListener(
    'hardwareBackPress',
    this._onBackPressAndroid
  )

  willBlur = () => BackHandler.removeEventListener(
    'hardwareBackPress',
    this._onBackPressAndroid
  )

  render() {
    <>
      { Platform.OS === 'android'
        <NavigationEvents
          onDidFocus={this.didFocus}
          onWillBlur={this.willBlur}
        />
      }
      { /* your component render */ }
    </>
  }
}

Upvotes: 2

Related Questions