nativescript-angular icon indicating copy to clipboard operation
nativescript-angular copied to clipboard

NgOnDestroy - ClearHistory - Custom NSRouteReuseStrategy

Open mpht opened this issue 6 years ago • 4 comments

Bug Short Version:

When using a custom NSRouteReuseStrategy navigating with clearHistory does not call ngOnDestroy. Without custom NSRouteReuseStrategy ngOnDestroy is called as expected.

Bug in more Detail:

Custom NSRouteReuseStrategy Imagine we have 3 Pages: P1, P2 and P3 We Start with P1 then navigate to P2 and then to P3

  1. P1 ngOnInit() is called
  2. P2 ngOnInit() is called
  3. P3 ngOnInit() is called

Then navigate to P1 with clearHistory this.nav.navigate(["P1"], { clearHistory: true }); ngOnDestroy is NOT CALLED for P3, P2 and P1.

Without custom NSRouteReuseStrategy We Start with P1 then navigate to P2 and then to P3

  1. P1 ngOnInit() is called
  2. P2 ngOnInit() is called
  3. P3 ngOnInit() is called

Then navigate to P1 with clearHistory this.nav.navigate(["P1"], { clearHistory: true }); ngOnDestroy is called for P3, P2 and P1 (as expected).

To Reproduce I have created a Playground: https://play.nativescript.org/?template=play-ng&id=1TvIZG&v=3

  1. Launch it and then press the NEXT button a few times.
  2. Press the P1 [CLEAR] HISTORY button (App will navigate to P1 with clearHistory: true - See *Info)
  3. Take a look at the logs (Press TOGGLE LOGS - top right corner)
  4. Hide the logs again (Press TOGGLE LOGS - top right corner)
  5. Press P1 [FORCE CLEAR] HISTORY (App will navigate to P1 CustomRouteReuseStrategy will call clearCache See *Info)
  6. Take a look at the logs - NgOnDestroy() is called

*Info: Step 2) P1 [CLEAR] HISTORY just calls this.nav.navigate(["P1"], { clearHistory: true }); Step 5) P1 [FORCE CLEAR] HISTORY calls this.nav.navigate(["P1"], { queryParams: { forceClearHistory: true } }); The CustomRouteReuseStrategy checks the queryParams and if forceClearHistory is true it calls this.clearCache(current.outlet);

PS: You can uncomment / comment the following lines in app.module.ts to see what I mean

        {
            provide: RouteReuseStrategy,
            useClass: CustomRouteReuseStrategy
        }

Expected behavior Maybe it is the expected behavior but this is what I was expecting: If I navigate with clearHistory: true this.nav.navigate(["P1"], { clearHistory: true }); I expect that NgOnDestroy() is called on all pages in the history stack.

mpht avatar Oct 21 '19 13:10 mpht

Noticed the same issue, the following config served as a workaround for me in app.module.ts.

Not sure if a bug or documentation issues. I think it is because PageRouterOutlet injects NSRouteReuseStrategy rather than RouteReuseStrategy type.

 providers: [ CustomRouteReuseStrategy,
    {
      provide: RouteReuseStrategy,
      useExisting: CustomRouteReuseStrategy
    }
    ,{
      provide: NSRouteReuseStrategy ,
      useExisting: CustomRouteReuseStrategy
    }]

mircopolo avatar Nov 04 '19 18:11 mircopolo

@vakrilov Ran into this today as well - is this a regression in the latest? Don't believe it always worked this way?

NathanWalker avatar Nov 26 '19 07:11 NathanWalker

@NathanWalker definitely a regression. I've just noticed this in our live apps that used to work properly on NS7.

EDIT: I have to clarify that this is happening to me even WITHOUT using a custom strategy EDIT2: The workaround does not seem to be working for me. The cache is being cleared, but ngOnDestroy is not being called, even when explicitly returning false from shouldReuseRoute

nikoTM avatar Jan 07 '22 14:01 nikoTM

As a temporary workaround that works for me, I am using this:

@HostListener('unloaded')
  cleanup() {
    if (!this.routerExtensions.canGoBackToPreviousPage()) {
      this.ngOnDestroy()
    }
  }

You could also do the same with Page.navigatedFrom

EDIT: A caveat this workaround won't work for the following flow: Page A -> Page B -> Page C -> (navigated with clearHistory) Page A

Page A's ngOnDestroy won't be called, where previously C->A clearHistory navigation took care of that

EDIT2:

When the application is put to the background (switching away) unloaded is called. So you might want to check for that before calling destroy.

nikoTM avatar Jan 07 '22 18:01 nikoTM