Mani Kant Tiwari
Mani Kant Tiwari

Reputation: 441

React-native: Removing BackHandler in different screen

I am new to react-native. I have two screens screen A and screen B. I register BackHandler event listener in screen A and want to remove the listener on screen B. How can I do it. I tried the following code.

class ScreenA extends React.Component{
    componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
    }
    handleBackPress = () => {
        return true;
    }
    _navigateToB = () => {
        this.props.navigation.navigate('ScreenB')
    }
    render(){
      return <View><Botton onPress={ () => { this._navigateToB } } /></View>
    }
}

// second screen
class ScreenB extends React.Component{
    componentDidMount() {
        BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress )
        //BackHandler.removeEventListener('hardwareBackPress', () =>  true )  //I tried it too
        //BackHandler.removeEventListener('hardwareBackPress', true ) //I tried it too
    }
    handleBackPress = () => {
        return true;
    }
}

But this code is not removing the backHandle event listener. and when I put the BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress ) in _navigateToB of screen A then it is working fine. Can I remove this listener on the screen B

Upvotes: 2

Views: 3203

Answers (1)

Lenoarod
Lenoarod

Reputation: 3620

firstly, in component B you don't register the BackHandler, so when you remove it, it reports the error.

Secondly, when you put it in the _navigateToB of screen A, you register it in the component A componentDidMount method before, so you can remove it.

you can not remove it on a different screen.

if you want to know more, we can see it source code:

const _backPressSubscriptions = [];
addEventListener: function(
    eventName: BackPressEventName,
    handler: Function,
  ): {remove: () => void, ...} {
    if (_backPressSubscriptions.indexOf(handler) === -1) {
      _backPressSubscriptions.push(handler);
    }
    return {
      remove: (): void => BackHandler.removeEventListener(eventName, handler),
    };
  },

it put the handler function in a array; and it is not global. so you only can add and remove in the same component.

then in the android native, when it receive the hardware back event, it will send it to the react native js.

// located in the DeviceEventManagerModule
/** Sends an event to the JS instance that the hardware back has been pressed. */
  public void emitHardwareBackPressed() {
    getReactApplicationContext()
        .getJSModule(RCTDeviceEventEmitter.class)
        .emit("hardwareBackPress", null);
  }

in the react native BackHandler.js source code, we can it add this event use RCTDeviceEventEmitter.

const DEVICE_BACK_EVENT = 'hardwareBackPress';
RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() {
  for (let i = _backPressSubscriptions.length - 1; i >= 0; i--) {
    if (_backPressSubscriptions[i]()) {
      return;
    }
  }

  BackHandler.exitApp();
});

so when we receive the event, it will pick the events which we add in _backPressSubscriptions before, when it reaches the end, it calls exitApp method.

Upvotes: 2

Related Questions