I'm attempting to override the back button on a screen with a prompt to Logout. See the following:
import React, { Component } from "react";
import { Alert, BackHandler } from "react-native";
export default class Dashboard extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress",this.handleBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackPress);
}
handleBackPress() {
Alert.alert(
"Logout",
"Are you sure you want to logout?",
[
{
text: "Cancel",
onPress: () => {
console.log("Cancel Pressed");
},
style: "cancel"
},
{ text: "Logout", onPress: () => this.handleLogout() }
],
{ cancelable: false }
);
}
handleLogout() {
this.props.navigation.navigate("Login");
}
}
As you can see, on mounting change, I'm binding and unbinding "hardwareBackPress" to this.handleBackPress. Note, I have to use .bind(this), otherwise I get
_this2.handleLogout is not a function
when I press the Logout in the Alert. Expected functionality is:
- Back button is pressed
- Functionality disabled (doesn't navigate)
- Alert is displayed
- Ok is pressed
- Navigates back
- Back button on previous screen has default action
But what actually happens is:
- Back button is pressed
- Navigates back
- Alert is displayed
- (Subsequent steps don't matter)
I noticed I don't have return true; anywhere in my handleBackPress(), so I added that:
handleBackPress() {
Alert.alert(
"Logout",
"Are you sure you want to logout?",
[
{
text: "Cancel",
onPress: () => {
console.log("Cancel Pressed");
},
style: "cancel"
},
{
text: "Logout",
onPress: () => {
return this.handleLogout();
}
}
],
{ cancelable: false }
);
return true;
}
But what happens now is:
- Back button is pressed
- Functionality disabled (doesn't navigate)
- Alert is displayed
- Ok is pressed
- Navigates back
- Back button press on previous screen results in Alert being displayed
I have verified that componentDidUnmount() is called, but it doesn't seem to have removed the event listener.
Has anyone encountered this issue before? For now, I've just resorted to globally disabling the back button by adding this handler at the entry point of the app, but that's not a long-term solution.
Edit: I noticed there's a lifecycle alternative, so I tried implementing that:
componentDidMount() {
this.backHandler = BackHandler.addEventListener("hardwareBackPress", () => {
Alert.alert("Logout", "Are you sure you want to logout?", [{ text: "Cancel", onPress: () => {}, style: "cancel" }, { text: "Logout", onPress: () => this.handleLogout() }], { cancelable: false });
return true;
});
}
componentWillUnmount() {
this.backHandler.remove();
}
And while this makes it work (somehow), it has yet another side-effect. As soon as I navigate forward (which doesn't trigger componentDidUnmount(), due to stacked navigation), and navigate back, the back button behaves as such:
- Back button is pressed
- Functionality disabled (doesn't navigate)
- Alert doesn't show up
The screen I'm navigating forward to has it's back button overridden, and seems to not play well with this alternative lifecycle. Will attempt to implement different approach on all subsequent screens; see if it behaves properly then.