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
feat: add ability for routing integrations to not cache views #19531
Comments
same happens with React apps |
This is a test case for ionic-team#19531.
I added a test case for this to the Angular test app in this repro, which shows a diffrent flavor of this issue quite well. Would love to create a PR for that and I am looking for a fix! Steps to reproduce with this test:
Now we are on page 2 and can see a back button. This is different from my repro app, but not correct, too. If I click on page I get redirected to |
My further debugging results.Views are reused from the stack if they are navigated to the second time. This line is responsible for losing the history after the first appearance of the view after using it the second time: https://github.com/ionic-team/ionic/blob/bfb704e2d2abf7a1e95e00e65206488c5a3558b7/angular/src/directives/navigation/stack-utils.ts#L24 Example for my theoryWe navigate from 1 to 3 and the history looks like
Now navigate to page 2 again after page 3 and the histoy looks like this
Because page 2 is reused the history rewinds to it's first appearance and I get back unexpectedly to my start point. I debugged this with console.log in stack-controller: setActive(enteringView: RouteView): Promise<StackEvent> {
console.debug("VIEW", this.views);
let { direction, animation } = this.navCtrl.consumeTransition();
const leavingView = this.activeView;
const tabSwitch = isTabSwitch(enteringView, leavingView);
if (tabSwitch) {
direction = 'back';
animation = undefined;
}
const viewsSnapshot = this.views.slice();
let currentNavigation;
const router = (this.router as any);
// Angular >= 7.2.0
if (router.getCurrentNavigation) {
currentNavigation = router.getCurrentNavigation();
// Angular < 7.2.0
} else if (
router.navigations &&
router.navigations.value
) {
currentNavigation = router.navigations.value;
}
/**
* If the navigation action
* sets `replaceUrl: true`
* then we need to make sure
* we remove the last item
* from our views stack
*/
if (
currentNavigation &&
currentNavigation.extras &&
currentNavigation.extras.replaceUrl
) {
if (this.views.length > 0) {
this.views.splice(-1, 1);
}
}
const reused = this.views.includes(enteringView);
console.debug("!!REUSED!!!!!!!!!!", reused);
const views = this.insertView(enteringView, direction);
// Trigger change detection before transition starts
// This will call ngOnInit() the first time too, just after the view
// was attached to the dom, but BEFORE the transition starts
if (!reused) {
enteringView.ref.changeDetectorRef.detectChanges();
}
// Wait until previous transitions finish
return this.zone.runOutsideAngular(() => {
return this.wait(() => {
// disconnect leaving page from change detection to
// reduce jank during the page transition
if (leavingView) {
leavingView.ref.changeDetectorRef.detach();
}
// In case the enteringView is the same as the leavingPage we need to reattach()
enteringView.ref.changeDetectorRef.reattach();
console.debug("AFTER VIEWS", this.views);
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
.then(() => ({
enteringView,
direction,
animation,
tabSwitch
}));
});
});
}
|
Show difference for ionic-team#19531
I found a possible workaround! Exisiting pages are reused if the URL matches. If I open an existing page a seconde time using a different URL it looks like the back button works as expected. Nevertheless there should be a fix for this. Since I'm not really sure how pages should be reused, I'm unsure how to fix this. |
Sorry for pushing this, but is this considered as a bug? Now I have to do an ugly workaround and add to every page a garbage random paramter to avoid this caching issue. I would like to remove that as soon as possible. |
Sorry but bumping this again to prevent getting this locked. |
Thanks for the issue. By default, all of our routing integrations will re-use existing views if they match the same URL. For example:
While this is working as intended, I can understand that this may not be expected or desirable in some situations. Changing this would be a breaking change that we can look into, or we can look into making this an opt-in feature. Either way there is certainly going to need to be some discussion about how to implement this. For anyone who is running into this scenario: Would you be able to provide a use case and a code sample that can help us understand how this behavior affects your applications? Thanks! |
I had a similar problem and solved it by defining multiple routes with similar path. Now when you go down the herarchy, new view is created each time. export const View = () => (
<IonReactRouter>
<IonSplitPane contentId="main">
<Menu />
<IonRouterOutlet id="main">
<Route path="/module" component={Module.List} exact />
<Route path="/module/:f1" component={Module.List} exact />
<Route path="/module/:f1/:f2" component={Module.List} exact />
<Route path="/module/:f1/:f2/:f3" component={Module.List} exact />
<Route component={NotFound} />
</IonRouterOutlet>
</IonSplitPane>
</IonReactRouter>
); I was surprised by this behavior at first, thought it was a bug in my app, but then I figured that Ionic must be doing some caching. After using the above setup, it works. I think it's a cool feature, but needs to be mentioned more in the docs. Maybe with nice big bold font :) |
At Moodle we're migrating the mobile app from Ionic 3 to Ionic 5, and we've found that this breaks some navigation we relied upon before; in the fashion I outlined in #23455. In particular, Moodle is an LMS (learning management system) with a lot of customization options. Given the nature of our software, there is a lot of interconnected pages. The specific scenario where we found this breaking down is navigating between pages in a course. Imagine that you are doing an activity linking to a section from another activity (a very common scenario). In this case, it is desirable to preserve the navigation stack in case you want to go back to the activity you came from. If you want to look at the code you can find it here: https://github.com/moodlehq/moodleapp |
Hi there, Thanks for filing the issue and providing more context around the various use cases. The team has decided not to implement this feature. Caching views allow us to improve performance on lower end devices and add functionality such as swipe to go back on iOS. Removing this functionality would make it more difficult to have a performant swipe to go back gesture. The use case in #19531 (comment) mentioned linking to other pages in a single course. This kind of pattern would benefit from parameterized URLs. By using parameterized URLs you can ensure that Ionic creates new instances of the same component whenever the parameters in the URL change. For example, given a routing configuration of I am going to close this. Thanks! |
@liamdebeasi Thanks for the update. We are already using parametrized urls in our app, the problem is that as I mentioned in #23455 we can have pages linking to the exact same page that is already in the stack. For example, imagine that Wikipedia builds an Ionic app. If you start navigating between articles, you'll eventually end up in a page you already visited. But you wouldn't want to lose all the navigation history. One solution would be to add a parameter that is a unique id in every route, which isn't related to the content of the page (maybe that's what you meant?). I guess that would work, but it'd be cumbersome to do that for every route in the app. And it doesn't make for pretty urls (although that's not a problem for us since we don't publish our app as a website). In any case, thanks for letting us know about your decision. We'll try to find some workarounds in our side. |
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. |
Bug Report
Ionic version:
[x] 4.x
Current behavior:
It looks like the back button does not show up in some cases when it should. This happens if one page gets opened a second time.
Possibly pages get initialized without 'can-go-back' and this does not get updated.
Wrong behavior:
My app opens a "list page" which can open a "detail page" which can open the "list page" with other query params again. This "list page" does not show an
ionic-back-button
.Expected behavior:
I would expect the
ionic-back-button
to show on the last "list page" and take me back to the "detail page" and from there anotherionic-back-button
to the first "list page".Steps to reproduce:
-> There is no back button
If I use the list page from menu, the back-button will show on the home page. But if I go to the list page again from there, the button will disappear as well.
Related code:
This is my test case.
Other information:
Ionic info:
New menu template
The text was updated successfully, but these errors were encountered: