feat: Lifecycle events not working on IonNav components
Prerequisites
- [X] I have read the Contributing Guidelines.
- [X] I agree to follow the Code of Conduct.
- [X] I have searched for existing issues that already report this problem, without success.
Ionic Framework Version
v7.x
Current Behavior
If I try to use the Lifecycles on Nav components it does not work.
Navigating between Components inside a IonNav does not fire the lifecycle hooks.
This is frustrating because I want to handle the BackButton event on specifict components but i can't if i don't have this hooks If i handle it in a useEffect then if i have 4 nav components mounted it will trigger the backButton in all of 4, and I only want to trigger on the current view.
Expected Behavior
To have the Lifecycles working on the nav components
Steps to Reproduce
- Start in a page with
<IonNav /> - Push another page that have
IonViewWillEnterandIonViewWillLeave - Then go back
You will see that neither of those hooks will trigger
Code Reproduction URL
https://github.com/FernetB/ionic-tabs-bug No response
Ionic Info
Ionic:
Ionic CLI : 7.1.1 Ionic Framework : @ionic/react 7.7.4
Capacitor:
Capacitor CLI : 5.2.3 @capacitor/android : 5.2.3 @capacitor/core : 5.2.3 @capacitor/ios : 5.2.3
Utility:
cordova-res : 0.15.1 native-run : 1.7.2
System:
NodeJS : v18.16.0 npm : 9.5.1 OS : Windows 10
Additional Information
No response
Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.
Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.
For a guide on how to create a good reproduction, see our Contributing Guide.
Added code reproduction, but I guess if u are requesting me that, implies that lifeclycle should work on ionNav
Thank you for the reproduction, and apologies for the delay. We ask for a repro in order to better understand the problems you're running into. Routing-related issues in particular can get complicated, so it's best to see the code directly.
The lifecycle events you've linked to are specific to routing (mapping URL paths to pages), which IonNav is not meant to be used for. (This is described at the top of the Nav docs.) The lifecycle events are not expected to fire when pushing ExploreContainer in an IonNav. IonNav does have its own lifecycle events, which you may find useful: https://ionicframework.com/docs/api/nav#events
However, I would expect the lifecycle events to fire when landing on or leaving the /nav-bug path, since that triggers a routing change on the Outside view. This is not currently happening because Outside does not use the IonPage component, which is required for routing. If I wrap Outside in <IonPage></IonPage>, the lifecycle hooks fire as expected.
Can you try the IonNav events and/or wrapping your views in IonPage and let me know if that works for your use case?
Yes, the events are working, the problem is that i don't have a simple way to know when a component pushed by a nav is active or not. With the route's lifecycles that would be easy to do, but without it is nearly impossible. For example, if i want to handle the hardware back button on each view differently with the current tools seems impossible because the "mounted" nav components that are hidden will be also listening to the back button and this will lead to unwanted behaviors. (With router lifecycles i could subscribe in the ionViewWillEnter and unsubscribe in the ionViewWillLeave)
If the ionNavWillChange event included what component is entering, would that solve things for you? Currently it doesn't emit any detail.
Yes, i think it could solve it, but it would be a lot better if you could do something like the useIonViewWillEnter/Leave methods that can be used inside the components. That would be much cleaner.
I think that if you could know wich component is on view and wich isn't because of the ion-page-hidden logic. You could do what i said before, i'm correct?
I spoke with the team on this, and there are a couple of other solutions that may work better:
- Using
IonNav's existinggetActivemethod to determine the active view. This could be done in your hardware back button listener, for example, to customize the logic. - Whenever a new component is pushed to the nav, register its hardware back button handler using a higher priority than the last (such as by using a private variable that gets incremented each time). Only the highest priority handler will be called by default. You can see more info in the hardware back button docs: https://ionicframework.com/docs/developing/hardware-back-button
Can you let me know if either of these work for your use case, and if neither of them do, why not? I want to make sure any features we add will solve your use case without needing extra unneeded APIs.
I tried the first but didn't succeed because i didn't know how to do the comparition between the getActive view and the components to know if they were visibles or not.
The second one may work, i didn't tried it, but i found it a bit hacky. It is like i have clean and simple solutions for routing but with nav i have to do things that aren't elegant or simple, and can lead to bugs, but it is okay, if you don't want or can't adds this features i will find a workaround.
But i want to leave my opinion that routing in react is the weakest part of ionic by far, and with nav that could have change a bit if at least has the same lifecycles hooks that routing has.
Thank you for the details. After talking with the team about this some more, we agree that there is room to improve with the way lifecycle events are handled in IonNav. I'll import the ticket as a feature request since we may be adding new behavior.
Note that any changes will also apply to Vue, since the two routing integrations have very similar code.
That's awesome, thank you!