Ionic-framework: bug: Nested IonRouterOutlet prevents component unmount

Created on 24 Feb 2020  Â·  22Comments  Â·  Source: ionic-team/ionic-framework

Bug Report

Ionic version:


5.0.1

Here is a repo with a minimal code to reproduce the bug:
https://github.com/OoDeLally/ionic-nested-router-outlet-bug

Ionic info:

â–¶ ionic info 

Ionic:

   Ionic CLI       : 5.4.16 (/home/pascal/.nvm/versions/node/v8.16.0/lib/node_modules/ionic)
   Ionic Framework : @ionic/react 5.0.1

Utility:

   cordova-res                          : not installed
   native-run (update available: 0.3.0) : 0.2.9

System:

   NodeJS : v8.16.0 (/home/pascal/.nvm/versions/node/v8.16.0/bin/node)
   npm    : 6.4.1
   OS     : Linux 4.15


react

Most helpful comment

Hello all,

I'm looking into this now, hope to have something to report on soon.

All 22 comments

Hi, any news of this?
I've tried to investigate checking the source code, but it seems beyond my level of understanding.

All of these issue links show the same problem that I am having trouble with. I replaced IonRouterOutlet with Switch, but IonTabs requires IonRouterOutlet, and I must delete IonTabs, and the app looks like ugly.
Probably, the problem is caused by IonRouterOutlet.
https://github.com/ionic-team/ionic/issues/20844
https://github.com/ionic-team/ionic/issues/20597
https://github.com/ionic-team/ionic/issues/20298
Duplicate of #20298 #20597 #20844

Anybody? This is a huge blocker for me

For me too... So far the workaround we use is to force a complete page reload (window.location = '...').
But this is definitely ugly, as the whole page flickers and we lose the parent state.

window.location

No, God, please, no :) Try this https://github.com/ionic-team/ionic/issues/20707#issuecomment-598806108

window.location

No, God, please, no :) Try this #20707 (comment)

It doesn't work for us.
When using <Switch>, the parent component successfully unmounts, but it also unmounts when it should not (when the path changes but should still keep the parent component mounted), leading to a blank page, without any kind of console error.

Staying with window.location = '...' for now, regarless of how ugly it is.

window.location

No, God, please, no :) Try this #20707 (comment)

It doesn't work for us.
When using <Switch>, the parent component successfully unmounts, but it also unmounts when it should not (when the path changes but should still keep the parent component mounted), leading to a blank page, without any kind of console error.

Staying with window.location = '...' for now, regarless of how ugly it is.

Did you try Ionic lifecycle methods?
Especially this one
useIonViewDidLeave(() => { console.log('ionViewDidLeave event fired'); });

Did you try Ionic lifecycle methods?
Especially this one
useIonViewDidLeave(() => { console.log('ionViewDidLeave event fired'); });

I just did. None of the 4 events in https://ionicframework.com/docs/react/lifecycle was fired.

I'm also experiencing the same issue, no lifecyle method will be fired. Tried both class and functional component using the ionic docs.

Hello all,

I'm looking into this now, hope to have something to report on soon.

Hi All,

We have a dev release that provides better support for nested IonRouterOutlet components. There is a new prop on IonRouterOutlet that lets the router know it is a nested outlet to better perform the transition.

If your'e outlet is a nested outlet directly rendered by a Route in a parent outlet, then use the ionPage prop on the IonRouterOutlet. Here is an example:

App.tsx:

const App: React.FC = () => (
  <IonRouterOutlet>
    <Route path="/sub1" component={Sub1Outlet}  />
    <Route path="/sub2" component={Sub2Outlet} />
  </IonRouterOutlet>
);

Sub1Outlet.tsx:

const Sub1Outlet: React.FC = () =>  (
    <IonRouterOutlet ionPage>
      <Route path="/sub1" exact={true} 
        render={() => <Redirect to="/sub1/page" />} />
      <Route path="/sub1/page" component={Page1} exact={true} />
    </IonRouterOutlet>
  );

Sub2Outlet.tsx:

const Sub2Outlet: React.FC = () =>  (
    <IonRouterOutlet ionPage>
      <Route path="/sub2" exact={true} 
        render={() => <Redirect to="/sub2/page" />} />
      <Route path="/sub2/page" component={Page2} exact={true} />
    </IonRouterOutlet>
  );

If you can, could you try to install it and let us know if it fixes the issue and if you run into any others? To install it run:

npm i @ionic/[email protected] @ionic/[email protected]

If all goes good this should be available in the next Ionic release.

Thanks!

It didn't unmount the component for me. For now I will stick with routerDirection="back". Although it's not correct, it's working the way I need

The issue continues. There is no need for nested ionrouteroutlet. The problem occurs at only one router.
https://github.com/ionic-team/ionic-framework/issues/20298
https://github.com/ionic-team/ionic/issues/20844
https://github.com/ionic-team/ionic/issues/20597

@elylucas thanks for the fix! I'm noticing that going "back" from nested routes seems to have no transition animation when going back from a "level-3" nested route to a "level-2" nested route.

I first noticed this issue with a single layer of routes (no nesting) and an apollo query with the no-cache option. Desired outcome, anytime i navigate to page X it would re-query the backend. I was surprised to see it not making the query a 2nd or more times. After days of searching git issues and changing versions of apollo/ionic etc i tried a useEffect callback function and noticed it wasn't working which is what apollo's useQuery uses to refetch.

All that to say i think the not unmounting components on forward and none directions is a premature optimization.
What if we made this an option on the Route? or something? This way the dev has to opt into the optimization and isn't surprised by it. [If enough ppl +1s this idea i can start working on a PR]

It didn't unmount the component for me. For now I will stick with routerDirection="back". Although it's not correct, it's working the way I need

What did you apply routerDirection="back" on?

Hello @basicBrogrammer, I started working on a react app, currently it does not deviate much from the default one generated by ionic start with a side menu. It does not have nested routing.
I have pages on different routes and I noticed the components do not unmount when I navigate from one route to the other, which for my use case is not good, as I want to refresh the content that I show when the user selects a view from the menu.

I could work it around by replacing IonRouterOutlet with a Switch, and wrapping it an IonContent to give it an id, but I can not judge what kind of side effects it would have. I think that the existing apis should give the developer control on when the component under a route is persisted or not, once the user leaves the route.

I think this is similar to what you described on https://github.com/ionic-team/ionic-framework/issues/20597#issuecomment-682473789, if I understood it well.

Hi All,

We have a dev release that provides better support for nested IonRouterOutlet components. There is a new prop on IonRouterOutlet that lets the router know it is a nested outlet to better perform the transition.

If your'e outlet is a nested outlet directly rendered by a Route in a parent outlet, then use the ionPage prop on the IonRouterOutlet. Here is an example:

App.tsx:

const App: React.FC = () => (
  <IonRouterOutlet>
    <Route path="/sub1" component={Sub1Outlet}  />
    <Route path="/sub2" component={Sub2Outlet} />
  </IonRouterOutlet>
);

Sub1Outlet.tsx:

const Sub1Outlet: React.FC = () =>  (
    <IonRouterOutlet ionPage>
      <Route path="/sub1" exact={true} 
        render={() => <Redirect to="/sub1/page" />} />
      <Route path="/sub1/page" component={Page1} exact={true} />
    </IonRouterOutlet>
  );

Sub2Outlet.tsx:

const Sub2Outlet: React.FC = () =>  (
    <IonRouterOutlet ionPage>
      <Route path="/sub2" exact={true} 
        render={() => <Redirect to="/sub2/page" />} />
      <Route path="/sub2/page" component={Page2} exact={true} />
    </IonRouterOutlet>
  );

If you can, could you try to install it and let us know if it fixes the issue and if you run into any others? To install it run:

npm i @ionic/[email protected] @ionic/[email protected]

If all goes good this should be available in the next Ionic release.

Thanks!

This seemed like a promising take but it didn't work for me. I assume it's because I have the IonRouterOutlet wrapped in a Suspense component. I have resorted to putting up a 404 page. I feel this is much better than using a Switch which makes the app lose the lifecycle events and caching, and also the routing animations. I hope we will have that Redirect working in IonRouterOutlet soon.

Hello @basicBrogrammer, I started working on a react app, currently it does not deviate much from the default one generated by ionic start with a side menu. It does not have nested routing.
I have pages on different routes and I noticed the components do not unmount when I navigate from one route to the other, which for my use case is not good, as I want to refresh the content that I show when the user selects a view from the menu.

I could work it around by replacing IonRouterOutlet with a Switch, and wrapping it an IonContent to give it an id, but I can not judge what kind of side effects it would have. I think that the existing apis should give the developer control on when the component under a route is persisted or not, once the user leaves the route.

I think this is similar to what you described on #20597 (comment), if I understood it well.

I think if you replace IonRouterOutlet with a switch you won't get the ION transition animations. You can change the direction on the given route to "back" and it will reload .... or at least it did last time i played with it.

routerDirection

I added routerDirection back to any link going to the given route that i wanted to "remount"

what is the state on this issue?
Nested routes result in breaking third party libraries (replacing ionRouterOutlet with Switch works)
anyways navigation is crucial

what is the state on this issue?
Nested routes result in breaking third party libraries (replacing ionRouterOutlet with Switch works)
anyways navigation is crucial

You have to remember that replacing IonRouterOutlet with a Switch will mean converting all your useIonViewDidEnter with useEffects and lose animations.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danbucholtz picture danbucholtz  Â·  3Comments

RobFerguson picture RobFerguson  Â·  3Comments

brandyscarney picture brandyscarney  Â·  3Comments

vswarte picture vswarte  Â·  3Comments

MrBokeh picture MrBokeh  Â·  3Comments