ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
50.73k stars 13.52k forks source link

bug(vue): redirect route in onBeforeRouteLeave path changes but view does not refresh #27485

Closed peixin closed 1 year ago

peixin commented 1 year ago

Prerequisites

Ionic Framework Version

v5.x

Current Behavior

Intercept the route in onBeforeRouteLeave hook and replace to another route. The path has changed, but the component has not refreshed.(Only trigger developer service hot reload, the page can be rendered.)

Expected Behavior

Intercept the route in onBeforeRouteLeave hook and replace to another route. The path has changed, and the component has refreshed.

Steps to Reproduce

preview: https://ionic5-vue3-ts-example.vercel.app/

Steps to Reproduce

/courses -> /course/1/navigation --> /course/1/information --> [back] [intercept]

Expected Behavior

/courses -> /course/1/navigation --> /course/1/information --> [back] [intercept]
                                 --> /course/1/leave

Current Behavior

/courses -> /course/1/navigation --> /course/1/information --> [back] [intercept]
                                 --> /course/1/leave (path changed, Component still `Information`)

Code Reproduction URL

https://github.com/peixin/ionic5-vue3-ts-example

Ionic Info

Ionic:

Ionic CLI : 6.20.8

Utility:

cordova-res : not installed globally native-run (update available: 1.7.2) : 1.7.1

System:

NodeJS : v16.14.0 npm : 9.4.0 OS : macOS

Additional Information

minimal reproduction: https://github.com/peixin/ionic5-vue3-ts-example

preview: https://ionic5-vue3-ts-example.vercel.app

In App.vue using router-view can achieve the goal, but using ion-router-outlet will not work.

 <template>
   <ion-app>
-    <!-- <ion-router-outlet></ion-router-outlet> -->
-    <router-view></router-view>
+    <ion-router-outlet></ion-router-outlet>
+    <!-- <router-view></router-view> -->
   </ion-app>
 </template>

Even after upgrading all dependencies to the latest version, the problem still exists. (2023-05-16)

"@ionic/core": "7.0.6",
"@ionic/vue": "7.0.6",
"@ionic/vue-router": "7.0.6",
"core-js": "^3.6.5",
"ionicons": "7.1.0",
"typescript": "5.0.4",
"vue": "^3.2.21",
"vue-router": "4.2.0"
liamdebeasi commented 1 year ago

Thanks for the report. I can reproduce the reported behavior, but this does not appear to be a bug in Ionic. The problem here is this is not how ion-back-button is intended to be used. The intended behavior of ion-back-button is that it takes users back to the previous view they were on. Intercepting this routing behavior and taking users to a different view is an anti-pattern and can be confusing for people using your application.

For example:

/pageA --> /pageB

Clicking the ion-back-button on pageB should always take users back to pageA since that was the previous view they were on.


Based on the example provided, it sounds like a Navigation Guard would be a better fit for what you are trying to accomplish.

peixin commented 1 year ago

Thanks for the reply. I will adjust the code.

Also another question, if I want to implement going to a specific page A with with router.push({name: "A"}) but do not need animation, how do I do it?

I found no parameters to dynamically control whether animation is required or not, and none in the route definition.

peixin commented 1 year ago

Update. The issues using global Navigation Guard and using Component hook beforeRouteLeave are the same.

Returning to another page is a real need for some special pages. and vue-router implements it perfectly.

I found that navigation guards can intercept ionic vur router push/replace but does not work for back.

commit code preview: https://ionic5-vue3-ts-example.vercel.app

liamdebeasi commented 1 year ago

Sorry, my previous comment was confusing. When users click the ion-back-button, your application should never redirect to CourseLeave. Clicking the ion-back-button should always brings users back to the CourseNavigation page because that is the last view they were on.

I suggested using the a navigation guard because you can present an alert instead of pushing a page.

Here is an example:

import { Router } from "vue-router";
import { alertController } from '@ionic/vue';

const init = (router: Router) => {
  router.beforeEach(async (to, from, next) => {
    console.log(`${from.name?.toString()} --> ${to.name?.toString()}`);

    if (from.name === "CourseInformation" && to.name !== "CourseLeave") {

      const alert = await alertController.create({
        message: 'Are you sure you want to leave?',
        buttons: [
          { text: 'Leave', role: 'destructive' }, { text: 'Cancel', role: 'cancel' }
        ]
      });

      await alert.present();

      const { role } = await alert.onDidDismiss();

      if (role === 'destructive') {
        next({
          name: "CourseLeave",
          replace: true,
          query: {
            from: from.name as string,
            to: to.name as string,
          },
        });
      } else {
        // Cancel the navigation
        return next(false);
      }
    } else {
      next();
    }
  });
};

export default { init };
peixin commented 1 year ago

Thanks liamdebeasi, I have refactored the code.

ionitron-bot[bot] commented 1 year ago

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.