Preventing going back
Sometimes you may want to prevent the user from leaving a screen, for example, if there are unsaved changes, you might want to show a confirmation dialog. You can achieve it by using the beforeRemove
event.
The event listener receives the action
that triggered it. You can dispatch this action again after confirmation, or check the action object to determine what to do.
Example:
function EditText({ navigation }) {
const [text, setText] = React.useState('');
const hasUnsavedChanges = Boolean(text);
React.useEffect(
() =>
navigation.addListener('beforeRemove', (e) => {
if (!hasUnsavedChanges) {
// If we don't have unsaved changes, then we don't need to do anything
return;
}
// Prevent default behavior of leaving the screen
e.preventDefault();
// Prompt the user before leaving the screen
Alert.alert(
'Discard changes?',
'You have unsaved changes. Are you sure to discard them and leave the screen?',
[
{ text: "Don't leave", style: 'cancel', onPress: () => {} },
{
text: 'Discard',
style: 'destructive',
// If the user confirmed, then we dispatch the action we blocked earlier
// This will continue the action that had triggered the removal of the screen
onPress: () => navigation.dispatch(e.data.action),
},
]
);
}),
[navigation, hasUnsavedChanges]
);
return (
<TextInput
value={text}
placeholder="Type something…"
onChangeText={setText}
/>
);
}
Previously, the way to do this was to:
- Override back button in header
- Disable back swipe gesture
- Override system back button/gesture on Android
However, this approach has many important differences in addition to being less code:
- It's not coupled to any specific buttons, going back from custom buttons will trigger it as well
- It's not coupled to any specific actions, any action that removes the route from state will trigger it
- It works across nested navigators, e.g. if the screen is being removed due to an action in parent navigator
- User can still swipe back in the stack navigator, however, the swipe will be cancelled if the event was prevented
- It's possible to continue the same action that triggered the event