Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Navigation between pages from different nested IonRouterOutlet's breaks UI due to outlets overlap #20219

Closed
alekseykarpenko opened this issue Jan 17, 2020 · 11 comments
Labels
ionitron: needs reproduction a code reproduction is needed from the issue author package: react @ionic/react package

Comments

@alekseykarpenko
Copy link

Bug Report

Ionic version:

[x] 4.11.8 (latest)

Current behavior:
When trying to navigate between two pages from different IonRouterOutlets UI is flickering and breaks, as non active outlet is on the top of others, making all visible UI elements unreachable.

Expected behavior:
Navigation between two pages from different nested IonRouterOutlet's should be possible. Router outlets shouldn't overlap each other, correctly determining which of them is active now (on the top of others).

Steps to reproduce:

Basically, what I'm trying to do is navigation between two pages Home (/home) and List (/list), both of them are inside global IonRouterOutlet, and both have inner IonRouterOutet for their own nested routes, as described in Docs. And here is a deal: I want to navigate directly from nested route of Home (e.g. /home/welcome) to the nested route of the List (e.g. /list/:id) with correct page transition. And it even works... but only for the first time. Then there are 3 different outlets in DOM overlapping each other, two with z-index: 0 (one of them is needed), and another (incorrect) with z-index:101, so UI is blocked with transparent alien outlet.

Related code:

https://gist.github.com/alekseykarpenko/6e5c71f915cf53eeee896e24ab1ee562/7af928cff5ee6a6553d4fa899d22f5874cc9cb42

Other information:

❗️ Looks like this is strictly related to #18197, #18823, #18845 (all of those Angular issues have been opened since last summer).
The quick workaround for me here was moving List's nested routes into parent IonRouterOutlet:

<IonApp>
  <IonReactRouter>
      <IonRouterOutlet>
        {/*<Route path="/list" component={ListPage}/>*/}
        <Route path="/list" component={List} exact={true}/>
        <Route path="/list/:id" component={Item}/>
        <Route path="/home" component={HomePage}/>
        <Route path="/" render={() => <Redirect to="/home"/> } exact={true} />
      </IonRouterOutlet>
  </IonReactRouter>
</IonApp>

https://gist.github.com/alekseykarpenko/6e5c71f915cf53eeee896e24ab1ee562/7af928cff5ee6a6553d4fa899d22f5874cc9cb42

But that's not a real gold bullet, I want it back 😢 Actually, I have two reasons for that: 1) Use all power of React Router nested routes; and 2) Place Home inside Tabs View while List will not be there and add Side Menu to both of them within the global IonRouterOutlet.

Thoughts on fixing this
Even while both pages are in different nested outlets, they have same global outlet. Looks like navigation goes in right way, but outlet controller can't determine current active outlet, giving incorrect z-index.

Ionic info:

Ionic:

   Ionic CLI       : 5.4.11 (/Users/ak/.nvm/versions/node/v10.16.3/lib/node_modules/ionic)
   Ionic Framework : @ionic/react 4.11.8

Utility:

   cordova-res : not installed
   native-run  : not installed

System:

   NodeJS : v10.16.3 (/Users/ak/.nvm/versions/node/v10.16.3/bin/node)
   npm    : 6.9.0
   OS     : macOS Catalina

Best regards and thanks for all that you do 💪 Keep em going.

@ionitron-bot ionitron-bot bot added the triage label Jan 17, 2020
@elylucas elylucas added the package: react @ionic/react package label Jan 21, 2020
@ionitron-bot ionitron-bot bot removed the triage label Jan 21, 2020
@alekseykarpenko
Copy link
Author

@elylucas any plans on this? It should be a disgusting limitation while building an architecture of the future app ;(

@jcarignan
Copy link

jcarignan commented Mar 11, 2020

Any updates with this? @elylucas
The bug is also easy to trigger in the Ionic Conference React App demo by editing 3 lines:

src/components/Menu.tsx:65
remove routerDirection="none" on the IonItem

src/App:77
src/pages/MainTabs.tsx:18
add mode="ios" on the IonRouterOulet

Click from a "Navigate" link to an "Account" link and vice versa in the top left menu and the same visual ghosting glitch will occur.

What I find really confusing is how the docs says :

An IonRouterOutlet should also not be a descendant from another IonRouterOutlet.

@elylucas
Copy link
Contributor

Hi @alekseykarpenko, @jcarignan,

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/react@5.3.0-dev.202006222125.df37029 @ionic/react-router@5.3.0-dev.202006222125.df37029

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

Thanks!

@MrWillTurner
Copy link

Hi, I had the same problem where my app flickered when navigating and stop working at one point but, your dev release resolved it.

But instead of using two IonRouterOutlet I use only one them on my App page and a BrowserRouter on my 'EventPage' to create a page tab system.

App.tsx

       <IonReactRouter>
           <IonTabs>
               <IonRouterOutlet>
                   <Switch>
                       <Route path="/event/:id" component={EventPage} exact/>
                       <Route path="/newEvent" component={NewEventPage} exact/>
                       <Route path="/" render={() => <Redirect to="/home"/>} exact/>
                       <Route path="/home" component={Home} exact/>
                       <Route path="/tab2" component={Tab2} exact/>
                       <Route path="/tab2/details" component={Details}/>
                       <Route path="/tab3" component={Tab3} exact/>
                   </Switch>
               </IonRouterOutlet>
               <IonTabBar slot="bottom" color={"primary"}>
                   <IonTabButton tab="tab1" href="/home">
                       <IonLabel>Home</IonLabel>
                   </IonTabButton>
                   <IonTabButton tab="tab2" href="/tab2">
                       <IonLabel>Search</IonLabel>
                   </IonTabButton>
                   <IonTabButton tab="tab3" href="/tab3">
                       <IonLabel>Notifications</IonLabel>
                   </IonTabButton>
               </IonTabBar>
           </IonTabs>
       </IonReactRouter>
   </IonApp>

EventPage.tsx:

            <IonHeader>
                <IonToolbar color={"primary"}>
                    <IonButtons slot="start">
                        <IonBackButton defaultHref="/"/>
                    </IonButtons>
                </IonToolbar>
            </IonHeader>
            <IonContent>
                <BrowserRouter>
                    <ul className={"eventTabs"}>
                        <li><NavLink to={`${match.url}details`}  className="tab">Details</NavLink></li>
                        <li><NavLink to={`${match.url}tasks`} className="tab">Tasks</NavLink></li>
                    </ul>
                    <div className="content">
                        <Route path={`${match.url}details`}  component={EventDetails}/>
                        <Route path={`${match.url}tasks`} component={EventTasks}/>
                        <Redirect exact from={`${match.url}`} to={`${match.url}details`} />
                    </div>
                </BrowserRouter>
            </IonContent>
        </IonPage>

Thanks for the release.

@adamduren
Copy link
Contributor

Adding ionPage to the nested IonRouterOutlet fixed it for me. It seems like documentation for this is needed as well as updates to the Nested Routes section of Ionic React Navigation

@mauriceackel
Copy link

mauriceackel commented Feb 26, 2021

Hello @elylucas, is there any way to confirm that this solution is still working in ionic 5.5.4 with react router 5.2.0? I am using the following setup of my app:

    <IonApp>
      <IonReactRouter>
        <Switch>
          <Route path="/administration/" component={Administration} />
          
          <IonTabs>
            <IonRouterOutlet>
              <Route path="/list/" component={List} />
              <Route path="/account/" component={Account} />
              <Route path="/checkin/" component={CheckIn} exact />

              <Redirect from="/" to="/list/" exact />
            </IonRouterOutlet>

            <IonTabBar slot="bottom">
              <IonTabButton tab="list" href="/list/">
                <IonLabel>List</IonLabel>
              </IonTabButton>
              <IonTabButton tab="account" href="/account/">
                <IonLabel>Account</IonLabel>
              </IonTabButton>
              <IonTabButton tab="checkin" href="/checkin/">
                <IonLabel>Checkin</IonLabel>
              </IonTabButton>
            </IonTabBar>
          </IonTabs>
        </Switch>
      </IonReactRouter>
    </IonApp>

And inside my Account component I export the following:

function AccountRouter({ match }: RouteComponentProps): ReactElement {
  return (
    <IonRouterOutlet ionPage>
      <Route exact path={match.path} component={Account} />
      <Route path={`${match.path}details/`} component={Details} />
      <Route path={`${match.path}credentials/`}  component={Credentials} />
    </IonRouterOutlet>
  );
}

So I am basically using the setup as explained in the docs together with your fix proposed here. However, if I navigate to the subpage Details inside this nested Ion router outlet an back again, the following happens:

Bildschirmvideo.aufnehmen.2021-02-26.um.02.26.21.mov

I think there is also another issue. See as the ion-router outlet gets assigned the ion-page-invisible class here for a brief moment. I don't know why this would need to be set on the router outlet here. I have the suspicion that this is can also cause issues with re-rendering of images because in another component of mine, all images get rerendered if I do a page transition backwards.

Bildschirmvideo.aufnehmen.2021-02-26.um.02.29.40.mov

@I-am-abdulazeez
Copy link

Any solution... currently facing the same issue

@amandaejohnston
Copy link
Contributor

Hi folks, I wanted to circle back to this.

I've created an issue on the docs repo for the missing ionPage prop: ionic-team/ionic-docs#2183 I'll be following up on this in the near future.

As for the flickering issue: since the ionPage fix has since been released, and other changes have been made to routing since then, would it be possible to create a minimal repo replicating the issue using the latest version of Ionic 6?

@amandaejohnston amandaejohnston added the ionitron: needs reproduction a code reproduction is needed from the issue author label Feb 2, 2022
@ionitron-bot
Copy link

ionitron-bot bot commented Feb 2, 2022

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.

@amandaejohnston
Copy link
Contributor

Closing this out due to a lack of reproduction for the latest-mentioned issue, and the fact that the original issue has already been solved (the solution just needs documenting). If anyone is still encountering any problems mentioned here on the latest version of Ionic, please open a separate issue with its own code reproduction. Thank you!

@ionitron-bot
Copy link

ionitron-bot bot commented Mar 18, 2022

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.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Mar 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
ionitron: needs reproduction a code reproduction is needed from the issue author package: react @ionic/react package
Projects
None yet
Development

No branches or pull requests

8 participants