2

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

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I used it in the same method _navigateToB of screen A. working fine
@ManiKantTiwari, the function you add to the listener belongs to A, so you can in A method _navigateToB remove it. in B the register function is can not find it. and we have to remove it when A component unmount. because of the _backPressSubscriptions is like class static variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.