Navigation event listeners properly cleanup on unmount
Why it matters
Navigation listeners added via navigation.addListener() that are never unsubscribed accumulate across screen mounts. Each time the screen re-enters the stack — through forward navigation, tab switches, or deep links — another listener stacks on top of the previous ones. The result is duplicate event firings: a focus handler that fires once on first mount fires twice after the second mount, three times after the third. This causes duplicate API calls, doubled analytics events, and in apps with optimistic state updates, race conditions that corrupt UI state. CWE-401 (Memory Leak) and ISO 25010:2011 reliability both cover this class of resource leak.
Severity rationale
Low because listener leaks cause duplicate event firing and memory accumulation rather than data exposure or crashes, but they compound with every navigation cycle and degrade reliability over a session.
Remediation
Return the unsubscribe function from useEffect or useFocusEffect for every addListener call. Prefer useFocusEffect from React Navigation, which handles cleanup automatically:
import { useFocusEffect } from '@react-navigation/native'
import { useNavigation } from '@react-navigation/native'
function HomeScreen() {
const navigation = useNavigation()
useFocusEffect(
React.useCallback(() => {
const unsubFocus = navigation.addListener('focus', handleFocus)
const unsubBlur = navigation.addListener('blur', handleBlur)
// cleanup runs on screen blur and unmount
return () => {
unsubFocus()
unsubBlur()
}
}, [navigation])
)
}
If you use useEffect instead, the cleanup function is equally required:
useEffect(() => {
const unsub = navigation.addListener('beforeRemove', handleBeforeRemove)
return unsub // addListener returns the unsubscribe function directly
}, [navigation])
Audit every addListener call in the codebase and confirm each one has a corresponding cleanup path — report the count even when all are clean.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Mobile Navigation & Deep Linking Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-401 — Missing Release of Memory after Effective Lifetime
- iso-25010:2011 · reliability — Reliability — Resource Utilization
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-navigation-linking·automated