IonRouterOutlet view caching prevents ngOnDestroy during forward navigation
0 reputation · 09 Oct 2023, 20:41 UTC
0 reputation · 09 Oct 2023, 20:41 UTC
Ionic's IonRouterOutlet caches component instances in the DOM to preserve scroll position and state across forward navigation. This caching behavior means Angular's ngOnDestroy hook does not fire when navigating away from a page via routerLink or NavController.push. Instead, the component remains attached to the cached view until the stack is popped or cleared.
Developers subscribing to Observables, WebSocket connections, or interval timers in ngOnInit face a disposal gap: the standard Angular cleanup pattern relies on ngOnDestroy, which Ionic's view caching bypasses. The documented Ionic page lifecycle hooks—ionViewWillLeave and ionViewDidLeave—fire reliably during navigation transitions, but their relationship to Angular's change detection and zone execution order is not formally specified in the framework contract.
Heap snapshot analysis confirms retained component instances after repeated forward navigation, yet the exact conditions triggering cache eviction (memory pressure, stack depth limits, or explicit navigateRoot calls) remain implementation-dependent.
ionViewWillLeave or Angular's ngOnDestroy—provides the authoritative teardown signal for async subscriptions in a cached view?ionViewWillLeave executes before the component is detached from the DOM cache, or can race conditions with zone microtasks leave resources dangling?33275 reputation · 10 Oct 2023, 02:22 UTC
For async subscriptions inside an IonRouterOutlet page, ionViewWillUnload is the authoritative teardown signal, not Angular's ngOnDestroy. ionViewWillLeave tells you the page is navigating away, but the component remains attached to the DOM cache, so it is not a destruction hook. Use ionViewWillLeave to pause or unsubscribe from active streams while the view is cached, and reserve ionViewWillUnload for final disposal when the view is actually removed.
Ionic's IonRouterOutlet keeps component instances in the DOM during forward navigation to preserve scroll position and local state. Because Angular's ngOnDestroy is tied to component destruction, it is deferred until the page is popped from the navigation stack or the stack is explicitly cleared. Heap snapshots confirm the retained instance, but the exact conditions that trigger cache eviction—stack depth, memory pressure, or navigateRoot—are implementation-dependent and not guaranteed by a formal contract.
ionViewWillEnter, start subscriptions or timers that should run while the page is visible.ionViewWillLeave, unsubscribe from Observables, clear intervals, and close WebSocket connections. The component is still alive, so this prevents background work while the view is hidden.ionViewWillUnload, perform any final cleanup that must happen when the component is destroyed. This fires when the cached view is actually removed.ngOnDestroy for cleanup in this scenario; it will not run until the stack is unwound.There is no DOM-detachment race with ionViewWillLeave because the view is intentionally retained. The risk is assuming the component is destroyed when it is only hidden. The exact ordering of Ionic lifecycle events relative to Angular change detection and zone microtasks is not formally specified, so avoid scheduling teardown work in a way that assumes a particular microtask sequence.
Instrument ngOnInit, ngOnDestroy, ionViewWillEnter, ionViewWillLeave, and ionViewWillUnload with console.log, then navigate forward and back. You should see ionViewWillLeave fire immediately, ngOnDestroy remain silent until the stack is popped, and ionViewWillUnload fire only on final removal. A heap snapshot after repeated forward navigations will confirm the instance is retained.
Are you using IonRouterOutlet or a standard Angular RouterOutlet, and which Ionic version? Standard RouterOutlet destroys components on navigation, so ngOnDestroy is sufficient. If you are on IonRouterOutlet, the version matters because caching behavior is version-sensitive; confirm the exact version before relying on the pattern above.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.