@ionic/vue-router: Props not updating from route

Hi all, using @ionic/vue for a project. Need routes that point to specific displays of an object. Got that part working:

In routes:

[{
  path: '/',
    component: () => import('@/App.vue'),
    children: [
      {
        path: 'object/:objectId',
        component: () => import('@/views/SingleObject.vue'),
        props: ({params}) => ({ objectId: Number(params.objectId) })
      },
...

Problem arises when I navigate away from this page, and then navigate to the same route but with a different ID. Instead of updating the component’s props with the new ID, or tearing down the first instance of the component and creating a new one with the new props, Ionic appears to just serve up the original component. I only see the rendering of the new object if I perform a full page refresh.

On the component:

props: {
    objectId: { required: true, type: Number }
  }

And a watcher in setup():

    watch(
      () => props.objectId,
      (a, b) => {
        // reached only once
        debugger
      },
      { immediate: true }
    )

I was wondering if this might have something to do with IonPage, since I know Ionic has big trouble with any view component that isn’t wrapped in that component; maybe both routes resolve to the same instance of IonPage and that’s why the router doesn’t recalculate the prop from the route?

I doubt that’s the case though because I tried this:

<IonPage :key="router.currentRoute.value.params.flashcardId">

Idea being to access the route directly and force Ionic to generate a new instance for each path. But this has no effect.

As expected, both beforeRouteEnter() and ionViewDidEnter() hooks are firing.

Does anyone know what’s going on here?

see - fix(vue): pass in correct route to props function by liamdebeasi · Pull Request #22605 · ionic-team/ionic-framework · GitHub,

Props fn is now only called on initial render

Looks like you will need to use route params and convert to number

Thank you @aaronksaunders, I see how to fix my issue.

“Props fn is now only called on initial render”

I do want to flag that this is very much not the correct behaviour. PR #22605 is apparently fixing an issue with route params functions not working, full stop. But route params should also update when the route changes, at least according to the normal behaviour of vue-router (and just the conventions of routing).

@ldebeasi, can you confirm that “Props fn is now only called on initial render” is a bug, and not a feature?

Update: ripping out the prop function (i.e., replacing props: ({params}) => ({ objectId: Number(params.objectId) }) with props: true and mapping to Number on the component side does not resolve the issue.

This is the only way I could find to get vue-router to work as advertised in an Ionic context:

In setup function

    const trueObjectIdFromRoute = computed(
      () => router.currentRoute.value.params["objectId"]
    )

If you use the route param it should work, at least it did for my tests I ran locally

    const route = useRoute();
    console.log(route.params.objectId);

Someone reported a similar issue over the weekend.

Can you try the dev build listed on bug: ionic vue, not updating params when getting viewitem on route with params · Issue #23043 · ionic-team/ionic-framework · GitHub and let me know if it fixes the issue?

1 Like

Yes, this is working now! Thanks very much for your prompt action.

1 Like

Great! I will merge that PR in this week. Feel free to keep using that dev build, but I recommend updating to the latest stable version once the feature ships.

1 Like

Hi,
I am facing an issue similar to this.
I have a router (vue) like below. I see that the props function is called only once. From the link shared in your previous reply, it is not clear it fixes a scenerio something like this. Please let me know any workaround.

const routes = [
  {
    path: "/",
    name: "home",
    component: () => import("@/views/HomePage.vue"),
    props: (route) => {
      window.console.log(route);
      return { query: route.query.q };
    },
  }
]

( I inserted a log() just to confirm that it is called only once.)