Describe the Bug
In ionic 4, what is the way to unsubscribe from observables? In angular this should be in ngOnDestroy
function, however according with this issue(https://github.com/ionic-team/ionic/issues/15205) the previous page does not trigger it.
https://angular.io/guide/lifecycle-hooks#ondestroy
Related Code
https://github.com/777wills/destroy-ionicV4
Expected Behavior
Unsubscribe from observables in ngOnDestroy
.
Additional Context
https://github.com/ionic-team/ionic/issues/15205
That's not correct. The previous page trigger it when the component will be destroyed
Here https://github.com/ionic-team/ionic/issues/15633 says that Views 1 and 2 will not be destroyed.
This only happens if you keep the page alive. If you use the NavController of @ionic/angular
and use navigateForward then the first page keeps alive (you can see it in the code because you can go back - a great feature). But if you leave the page without the plan for coming back (e.g. with navigateRoot() ) the page will be destroyed and so ngOnDestroy fires
so why is this not working? I did:
ionic start myApp tabs --type=angular
Then I added the ngOnDestroy
in home page:
import { Component, OnDestroy } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss']
})
export class HomePage implements OnDestroy {
ngOnDestroy() {
console.log('HomePage destroyed!');
}
}
Using @ionic/angular 4.0.0-beta.12
Am I doing something wrong?
See the result:
Because the components will not be destroyed (they still exist) - you only forward to another tab. As you can see in the following screenshot all three tabs are available:
And now how to destroy it:
I add a button on home with the following:
this.nav.navigateRoot(['/dashboard']); //nav is NavController from @ionic/angular
And then you see the components (you opened) will be destroyed
I understand what you mean but in my project the tabs are a little bit different:
<ion-tabs>
<ion-tab icon="tennisball" href="/page-one">
</ion-tab>
<ion-tab icon="chatboxes" href="/page-two">
</ion-tab>
<ion-tab icon="person" href="/page-three">
</ion-tab>
<ion-router-outlet></ion-router-outlet>
</ion-tabs>
In theory, with ion-router-outlet
the previous page should be destroyed. When I use router-outlet
(angular), the component is destroyed and the ngOnDestroy
works fine.
Everything inside of the router should be replaced.
See how the page is hidden somehow:
If you just switch to another page, the old page is still in the stack because you can go back to this (as you can see your page-two has can-go-back
). Again: If you not want to go back, use
this.nav.navigateRoot(['/dashboard']); //nav is NavController from @ionic/angular
Then the old page will be removed from stack and the component will be destroyed
NavController is suggested for special cases only. For example (from the ion4 docs):
This fits use cases where you could have a modal, which needs it's own sub-navigation, but not make it tied to the apps URL.
The recommended router for Ionic 4 Angular is:
For apps the are built with Angular and @ionic/angular, we recommend using the Angular Router which comes out of the box for every new Ionic 4 Angular app. Previous versions of Ionic shipped with our own custom router, but in order to provide the best tooling and developer experience we have since moved to using the framework's recommended router.
With the Angular router the page should fire ngOnDestroy when you go back.
@paulstelzer are you suggesting I have to change all my href="path"
in my HTML pages to this.nav.navigateRoot([path])
because ionic framework will not destroy the page?
Isn't that an issue? I should be able to use Angular Router easily. As @berchik mentioned: Angular Router which comes out of the box for every new Ionic 4 Angular app
@jmchaves No! You have to include this into your sourcecode if you switch from one page to another. you can also use angular router of course, no problem. But with the Ionic NavController it's easier ;)
I cannot use href="path"
because the ngOnDestroy
will not be triggered. I am forced to use NavController if I want to unsubscribe from observables in ngOnDestroy
Besides, after switching the tabs a few times I found out the components inside of the ion-router-outlet
sometimes get duplicate. See:
I've seen this too. One of the things I've been excited about with ionic 4 is being able to just use the normal angular lifecycle hooks everywhere on pages AND subcomponents, but that depends on fully turning off the nav stack.
IMO it's not currently super clear how to make sure to avoid the nav stack if you don't want it in a way that works with tabs and without.
The ionic team seems to suggest avoiding the nav controller if you don't need the nav stack, but it doesn't seem to always do what you'd expect.
Maybe a clearer description for this issue would be more about the router.
With each beta release I've been waiting for a clear "if you want to use the nav stack and use the ionic lifecycle hooks, do ___. if you want to avoid the nav stack and use the angular lifecyclehooks, do ___. Any behavior otherwise is a bug." Otherwise it's not clear if we're seeing a bug or just not using it the way that's intended :(.
@captaincaius I agree with you. And definitely this is an ionic router issue.
So, can we just use angular native router-outlet in Ionic 4 app and how? Or any other strong recommendations?
@airstep I don't recommend change it to angular router-outlet because you'll miss animations and some styles. I did the test and the lifecyclehooks works perfect however you would need to add custom styles to fix what I mentioned before which doesn't make sense because we already have ionic to care of it.
So, in what version I can get this care? I get issue when return back from one screen to previous - where current stay on top of next. Bcz ngOnDestroy called only once in first, but in second time it is not...
@airstep, from what I know there are 3 temporary solutions (because we're waiting for Ionic Team answers here):
1) Set a timeout to unsubscribe the observable, something like this: https://angular.io/guide/observables#basic-usage-and-terms
2) Go back to Ionic 3.9.x and use ionViewWillLeave
: https://ionicframework.com/docs/api/navigation/NavController/
3) Or as @paulstelzer mentioned you can use navigateRoot
instead:
this.nav.navigateRoot([path]);
Does it make sense?
You can use href="path" as long as you include [routerDirection]="root". Just happened to notice this and tested in my app. ngOnDestroy gets called.
Regarding the lifecycles, for me this works as explained here: https://github.com/ionic-team/ionic/issues/15633#issuecomment-422430944. It makes sense and you shouldn't unsubscribe if your view hasn't been destroyed yet, otherwise you would be responsible of setting everything up again when the view becomes active again. If you want to use the Ionic Router Outlet, this is part of its behavior, although it would be great if the component allowed us to set if we want to keep a stack or not.
That said, this is not a bug but a feature request, maybe you can join the Slack channel and share your thoughts there: https://ionicworldwide.herokuapp.com/
On the other hand, the elements duplication would be a bug, but that should be discussed in a different issue with clearer steps about how to reproduce it. An example running in https://stackblitz.com/ would help a lot!
I created an article on Medium.com, hopefully it explains it now better (and I hope I am saying nothing wrong - maybe one of the Ionic team can take a look at it)
https://medium.com/@paulstelzer/ionic-4-and-the-lifecycle-hooks-4fe9eabb2864
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Most helpful comment
I've seen this too. One of the things I've been excited about with ionic 4 is being able to just use the normal angular lifecycle hooks everywhere on pages AND subcomponents, but that depends on fully turning off the nav stack.
IMO it's not currently super clear how to make sure to avoid the nav stack if you don't want it in a way that works with tabs and without.
The ionic team seems to suggest avoiding the nav controller if you don't need the nav stack, but it doesn't seem to always do what you'd expect.
Maybe a clearer description for this issue would be more about the router.
With each beta release I've been waiting for a clear "if you want to use the nav stack and use the ionic lifecycle hooks, do ___. if you want to avoid the nav stack and use the angular lifecyclehooks, do ___. Any behavior otherwise is a bug." Otherwise it's not clear if we're seeing a bug or just not using it the way that's intended :(.