Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BackAndroid/BackHandler Event Listeners are not Triggered when set in a Modal's Child Component

I am unable to set event listeners using the react-native BackHandler in a component that is placed inside a modal. I suspect that this happens because the modal is listening to the method that is passed on the onRequestClose prop.

Well, I am not sure if this is a bug or a feature request but I would suggest that you allowed us to pass a certain value (e.g null) to the onRequestClose prop as a way of flagging that there might be BackHandler event listeners being set in the Modal's child components, and that these listeners have priority (i.e override the onRequestClose of the Modal).

Environment

Environment:

  • OS: macOS High Sierra 10.13.3
  • Node: 9.2.0
  • Yarn: 0.24.6
  • npm: 5.6.0
  • Watchman: 4.7.0
  • Xcode: Xcode 9.2 Build version 9C40b
  • Android Studio: 3.0 AI-171.4408382

Packages: (wanted => installed)

  • react: 16.2.0 => 16.2.0
  • react-native: 0.53.0

    => 0.53.0

Steps to Reproduce

Below there is the instructions inside the child component:

class ChildComponent extends Component {
    componentDidMount () {
        BackHandler.addEventListener('hardwareBackPress', this._onBackPress)
    }

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

    _onBackPress = () => {
        console.log('Event was triggered')

        return true
    }

    render () {
        return (
            <Text>{'Some Text'}</Text>
        )
    }
}

export default ChildComponent

The component that has the Modal (parent) has the following instructions:

class ParentComponentWithModal extends Component {
    constructor (props) {
        super(props)
        this.state = {
            modalVisible: true
        }
    }

    render () {
        const { modalVisible } = this.state
        return (
            <View>
                <Modal
                    visible={modalVisible}
                    onRequestClose={() => console.log('onRequestClose')}
            >
                <ChildComponent />
            </Modal>
          </View>
        )
    }
}

export default ParentComponentWithModal

Expected Behavior

The _onBackPress method added to hardwareBackPressed listener should be executed when the back button is pressed.

Actual Behavior

When the back button is pressed, the function defined on the onRequestClose prop is triggered. Even if no function is defined on the onRequestClose prop, the methods attached to the event listeners defined in the modal's children are not executed.

like image 391
Marcelo Dauane Avatar asked May 06 '18 11:05

Marcelo Dauane


1 Answers

This behaviour is documented on React Native's site:

onRequestClose The onRequestClose callback is called when the user taps the hardware back button on Android or the menu button on Apple TV. Because of this required prop, be aware that BackHandler events will not be emitted as long as the modal is open.

So you will need to use the onRequestClose function instead of BackHandler.

<Modal
   visible={visible}
   onRequestClose={() => this.setState({ visible: false })}
>
like image 54
Francois Nadeau Avatar answered Nov 01 '22 02:11

Francois Nadeau