-
Notifications
You must be signed in to change notification settings - Fork 13.5k
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
fix(react): nested router outlets will not reanimate entered views #24672
Conversation
Looks like I need to address some issues with regards to failing tests. Need to validate that the criteria they are validating is accurate to expected behavior vs. testing the previous incorrect behavior. I also somehow completely missed that the react router package also has its own test app. I can likely remove all the custom changes to the react test app and just validate changes there. |
Ok, only one outstanding test is failing, which I will address in the morning.
I believe this test is covering incorrect behavior. Now when clicking the |
Verified in the reproduction app (from the attached issue) and the Ionic React conference app. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work, and thanks again for the live walkthrough! 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! One non-blocking comment.
if (enteringViewItem === leavingViewItem) { | ||
/** | ||
* If the entering view item is the same as the leaving view item, | ||
* we are either transitioning using parameterized routes to the same view | ||
* or a parent router outlet is re-rendering as a result of React props changing. | ||
* | ||
* If the route data does not match the current path, the parent router outlet | ||
* is attempting to transition and we cancel the operation. | ||
*/ | ||
if (enteringViewItem.routeData.match.url !== routeInfo.pathname) { | ||
return; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to only check if enteringViewItem.routeData.match.url !== routeInfo.pathname
?
If enteringViewItem === leavingViewItem
but enteringViewItem.routeData.match.url === routeInfo.pathname
then that would mean you went from /page/1
to /page/1
which I don't think is possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This specific check is to catch the difference in behavior between changing between tabs vs. pushing to another route that uses the same component.
With tabs and our reliance on React's re-rendering as a result of props changing to trigger route transition, the /tabs
component will reach this check when navigating between /tabs/tab1
to /tabs/tab2
. But, since the entering view item's rout date is /tabs
and not /tabs/tab1
, it will return early (skipping the unnecessary transition).
If pushing to the same detail page, the entering and leaving view item will be the same, but the entering view item's route will be /page/1
and the route info will be /page/1
, so the transition will occur.
I'm a little worried about opening up this check without the entering/leaving comparison, since this is the only case that is currently attempting to transition when it shouldn't. Ideally all of this goes away, if we move off React's re-rendering/prop changes for handling route transitions and follow closer suite to the Vue implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, let's keep it as is 👍
I have tried using version 6.0.4 but still got the same problem |
@shadowzack the problem still exists in v6.0.4. The comparison screenshots are comparing the incorrect behavior vs. the corrected behavior. You need to upgrade to 6.0.5 or later: https://github.com/ionic-team/ionic-framework/blob/main/CHANGELOG.md#605-2022-02-02 |
I have just tried version 6.0.5 and the latest 6.0.13, all have the same problem |
If you want to open an issue with a reproduction starter app, I would be happy to look. |
I have tried to build a test app with the latest ionic core 6.0.13, and the app works as indented with no flickering. |
If I recall, I verified this issue against the conference app and noticed an improvement to the transition between tab items (nested outlets). The only issue currently that I am aware of this is causing flicker transitions is fallback routes: #24855. If you are able to pull in the similarities between your application and a new project, to isolate the reproduction, I can give a better recommendation. Nested outlets are unfortunately complex to handle page transitions and mounting/unmounting with how we replicate native page transitions. |
this is the code above, after running the code without the outer IonRouterOutlet the tabs transition without flickering. i think this might be related to the fact that the side menu and the tabs have the same paths(for example home using tabs and also using the side menu) |
I have downloaded the ionic-react-conference-app, even without adding anything just running the code you can see the flickering when moving between tabs. can you try to fix it I think fixing it will help me and the anyone stuck in this problem. |
I have migrated back to ionic 5 until this issue is resolved, TIP - you can migrate back using this command:- |
Pull request checklist
Please check if your PR fulfills the following requirements:
npm run build
) was run locally and any changes were pushednpm run lint
) has passed locally and any fixes were made for failuresPull request type
Please check the type of change your PR introduces:
What is the current behavior?
When navigating within a nested router outlet, the page containing the router outlet is transitioning when the view is already visible. The most common instance of this, is when using nested router outlets in combination with IonTabs. When navigating between the tabs, the page containing IonTabs is transitioning, resulting in a flickering display.
Issue Number: #24107
What is the new behavior?
The logic for determining when a page transition should occur has been amended to account for the conditions that apply when you are either within a single router outlet or within a nested router outlet.
Navigating between tabs within a nested router outlet will no longer flicker, as all subsequent routing will not transition the page containing the router outlet.
For example, when navigating between
/tabs/tab1
to/tabs/tab2
, only the view elements fortab1
andtab2
will transition. The view element containing the/tabs
path and router outlet will not transition, as that view is already active in the viewport.Does this introduce a breaking change?
Other information
This change should have a noticeable performance improvement for React applications using nested router outlets. Prior to this PR, the page element was transitioning and causing multiple repaints, when the view was already active. This likely wasn't caught prior to the custom elements build, as Stencil's hydrated (
.hydrated
) class was overriding the styling fromion-page-invisible
.Kapture.2022-01-28.at.14.10.44.mp4