Reacting to router param change.
-
I have a router entry with
{path: 'strategy/net/:id', component: () => import('../')}, {path: 'strategy/manual/:id', component: () => import('../')},
and component pointing to it with
<q-item clickable v-ripple :inset-level="level/2" :to="router" exact>
where router is variable with entries such as
/strategy/net/foo1 /strategy/manual/foo2 /strategy/manual/bar1
Component is common for all pages (it’s navigation bar)
If i click on foo2 I go to foo2 page, however I can’t go to bar1 from foo2. The url in browser location bar changes, but component is not updated. I can get to bar1 from foo1 page.
I looked into vue manual and found this page: https://router.vuejs.org/guide/essentials/dynamic-matching.html#reacting-to-params-changes
Looks like it describes my issue precisely.
I use composition api and can’t figure out how can I force component to re-run setup() section and fetch data for new id. If would be nice if this behavior can be completely disabled somehow. -
You could use a watch in the setup:
setup() { const article = reactive({...}); function fetchArticle(id) { //assign article.. } watch('$route.params.articleId', fetchArticle) return { article }; }
Here is the article with some more solutions:
https://medium.com/js-dojo/watch-vue-route-params-query-with-composition-api-97b3c8c402e(if you can’t read it because medium wants you to register or pay 5$ , try to view it in an incognito chrome window):
-
This method doesn’t work if you are using typescript - you can’t pass a string as the first parameter to
watch
.I also tried the method where you create a hook like this and it’s not working either:
// router.js const route = Vue.observable<Route>({ fullPath: '', hash: '', matched: [], params: {}, path: '', query: {}, }); Router.afterEach((to) => { Object.assign(route, to); console.log({route}) // this console log always executes }); export const useRoute = () => computed(() => route);
// in the component setup() { const route = useRoute(); watch(route, (newVal) => console.log(newVal)); //this console log never executes }
It’s weird because the
console.log
in theafterEach
hook always runs but the one in the watcher never does… -
I found out why it wasn’t working for me - when the
Object.assign()
call is made it only modifies the properties and not the entire object so thecomputed
function is not actually triggered to rerun.This example works for my use case (hope it helps someone else
)
const routerState = Vue.observable<{route: Route}>({ route: { fullPath: '', hash: '', matched: [], params: {}, path: '', query: {}, }, }); Router.afterEach((to) => { Object.assign(routerState, { route: to }); }); export const useRoute = () => computed(() => routerState.route);
-
Thanks for help, I use ts, so I’ve altered @dobbel snipped to
watch(() => context.root.$route.params.id, (first, second) => { strategyCode.value = first });
Component uses a new id without any other coding, amazing.
-
@kernelconf that is crazy amazing I have wasted a lot of time since I am using typescript + 1.5.4 Quasar + Composition API and there is no useRoute function. Your solution works amazingly. Could you please describe how it technically works? Very interesting!