Jmh2013
Jmh2013

Reputation: 2777

Reactive Vue Router object by wrapping in ref() not working

I have an application where I would like to print the location of the user similar to a breadcrumb. I have a component that I add at the application level and expect it to update with current value or the router.currentRoute object. However it doesn't seem to be updating as expected.

I'm using the Vue2 Composition api plugin and am trying hard to keep it in a decent state that will make migrating to Vue3 much easier once I'm able. This means I'd like to avoid using the context.$route object that's available. My attempt currently imports the router directly and wraps the currentRoute object in a ref() but that doesn't seem to work.

Here is a CodeSandbox with an application that shows the issue. I have a home page and two additional pages. The text that reads 'Your current location is: Home` should change to the name of the other pages when navigating there, however it does not change at all.

<template>
  <div>
    <p>Your current location is: {{ location.name }}</p>
  </div>
</template>

<script>
import { defineComponent, ref } from "@vue/composition-api";
import router from "@/router";

export default defineComponent({
  name: "Page1",
  setup() {
    const location = ref(router.currentRoute);

    return { location };
  },
});
</script>

Please let me know if there is a way to do this the way I'd like. If it's not possible I'll just bite the bullet and use context.$route and deal with the larger refactoring when I migrate to Vue3.

Upvotes: 0

Views: 1906

Answers (1)

tony19
tony19

Reputation: 138526

You could use reactive() on the router instance, and then toRef() on that to get currentRoute:

import { defineComponent, reactive, toRef } from '@vue/composition-api'
import router from '@/router'

export default defineComponent({
  setup() {
    const location = toRef(reactive(router), 'currentRoute')
    return { location }
  }
})

Vue 2 demo

You'll probably migrate this in Vue 3 anyway because the next version of Vue Router already has different semantics for the Composition API. You could simply use useRoute() from Vue Router 4 in Vue 3:

import { defineComponent } from 'vue'
import { useRoute } from 'vue-router'

export default defineComponent({
  setup() {
    const location = useRoute()
    return { location }
  }
})

Vue 3 demo

Upvotes: 2

Related Questions