Broken back-button behavior is the most reliably reported UX defect in mobile app reviews. On Android, a hardware back press that skips a screen, crashes the app, or silently does nothing fails WCAG 2.2 SC 2.1.1 (Keyboard), which requires keyboard-equivalent navigation for all functionality. Beyond accessibility compliance, unexpected back behavior corrupts navigation state in ways that can strand users mid-flow — stranded on a checkout confirmation with no path to their cart, or dropped to an empty stack with no way to recover.
High because incorrect back-button behavior corrupts navigation state for all Android users and constitutes a keyboard accessibility failure under WCAG 2.2 SC 2.1.1, blocking users who rely on hardware navigation.
React Navigation handles the default back behavior automatically for most stack setups — only intervene when you need to intercept it (e.g., unsaved-form confirmation). Use useFocusEffect with BackHandler to manage the Android hardware back button on screens that need custom logic:
import { useFocusEffect } from '@react-navigation/native'
import { BackHandler, Alert } from 'react-native'
function EditFormScreen({ navigation }) {
const [isDirty, setIsDirty] = React.useState(false)
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
if (isDirty) {
Alert.alert('Discard changes?', '', [
{ text: 'Cancel', onPress: () => null },
{ text: 'Discard', onPress: () => navigation.goBack() },
])
return true // prevent default
}
return false // use default
}
BackHandler.addEventListener('hardwareBackPress', onBackPress)
return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress)
}, [isDirty, navigation])
)
}
For screens without custom needs, do not add a BackHandler at all — letting React Navigation's default behavior run is correct.
ID: mobile-navigation-linking.navigation-ux.back-button-behavior
Severity: high
What to look for: On Android, check for useFocusEffect or useEffect handling the hardware back button via BackHandler from react-native. On iOS, check for proper gesture handling of back swipe. Examine whether back button correctly pops from the current stack and handles nested navigators.
Pass criteria: Count all BackHandler event listeners and back navigation handlers in the codebase. Android back button navigates up exactly 1 level in the stack or exits the app when at the root. iOS back gesture works correctly. No more than 0 unintended screens are popped per back action.
Fail criteria: Back button crashes the app, navigates to an unexpected screen, or is unresponsive. Nested stack back behavior is broken.
Skip (N/A) when: Never — back button behavior applies to all mobile apps.
Detail on fail: Describe the issue. Example: "Pressing back on Android pops multiple screens instead of one" or "Back button on iOS is unresponsive in nested stacks"
Remediation: Handle back button behavior with React Navigation's built-in support and BackHandler on Android:
import { useFocusEffect } from '@react-navigation/native'
import { BackHandler } from 'react-native'
function ProductDetailScreen() {
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
// Return true to prevent default back behavior, false to use default
// Default behavior (return false) pops the current screen
return false
}
BackHandler.addEventListener('hardwareBackPress', onBackPress)
return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress)
}, [])
)
return <View>{/* screen content */}</View>
}
React Navigation handles most back behavior automatically — only customize if you need special handling (e.g., confirmation dialogs).