Back button behavior is correct for the platform
Why it matters
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.
Severity rationale
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.
Remediation
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.
Detection
-
ID:
back-button-behavior -
Severity:
high -
What to look for: On Android, check for
useFocusEffectoruseEffecthandling the hardware back button viaBackHandlerfromreact-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).
External references
- wcag:2.2 · 2.1.1 — Keyboard
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-navigation-linking·automated