useRoute() does not update with current route after upgrading from 3.11.2 to 3.12.0
Environment
Nuxt 3.12.0 Node Version: v20.12.2
Reproduction
// pages/testPage.vue
const { testFunctionWithUseRouteInside } = useTestStore()
const route = useRoute();
console.log(route.params); // { test: 123 }
await Promise.all([testFunctionWithUseRouteInside(), otherFunc()])
// stores/testStore.ts
const testFunctionWithUseRouteInside = () => {
const something = '' // ...
const route = useRoute();
console.log(route.params); // { }
return something
}
Describe the bug
Issue exists only after upgrading from 3.11.2 to 3.12 and so on.
It appears that page component has correct data inside useRoute(). However useRoute() inside store function holds 'previous route'.
Suggested workaround (https://github.com/nuxt/nuxt/issues/27199#issuecomment-2111055177) of using const route = useRouter().currentRoute.value; is not working correctly.
Additional context
No response
Logs
No response
what's happening if you run testFunctionWithUseRouteInside() on "onMounted()" lifecycle?
what's happening if you run testFunctionWithUseRouteInside() on "onMounted()" lifecycle?
Running in onMounted() seems fine, however above code is highly simplified :)
These functions must be SSR-friendly. SSR is fine, navigating via client seems to be broken
i think it is a normal behaviour because if you run the code outside "onMounted" lifecycle, you are almost in "creating", it means that you are still in the old page and the new one is still mounting in progress, it means that you are not landed yet in the new route, sometimes you can see this behaviour by using "destroy" on nuxt2 for example, it will runs after you are landed in the new route
i think it is a normal behaviour because if you run the code outside "onMounted" lifecycle, you are almost in "creating", it means that you are still in the old page and the new one is still mounting in progress, it means that you are not landed yet in the new route, sometimes you can see this behaviour by using "destroy" on nuxt2 for example, it will runs after you are landed in the new route
Everything was working fine prior to v_3.12 I wouldn't say it's normal, code inside page component is running so the route is already changed. Function inside store is called later than useRoute inside page, which has correct route info..
but the previous route is not destroyed yet at this point i would say
When navigating on client-side, there are two 'forks' of a suspense tree. One fork remains on the page displaying the old route. Inside this page the route remains the 'old' one. Another fork starts rendering the new route.
Because two routes 'exist' at the same time, we inject a route object inside each page that gets picked up by useRoute so that it 'matches' what's being rendered. Without doing this, you'd get flashing content + double mounts because the 'new' page being rendered would have a route that really belonged to the old page, OR, you'd have new route content bleeding through into the old page that was being rendered.
However, when useRoute is called outside a page context, we can't know which page it's being called from, so it gets a route object that only updates after the visible page has transitioned and suspense has resolved. This is so you don't get bits of your layout shifting before the actual main page has updated.
Possibly related issues:
- https://github.com/nuxt/nuxt/issues/14595
- https://github.com/nuxt/nuxt/issues/21340
- https://github.com/nuxt/nuxt/issues/24642
- https://github.com/nuxt/nuxt/issues/27199
Would you be able to provide a reproduction? 🙏
More info
Why do I need to provide a reproduction?
Reproductions make it possible for us to triage and fix issues quickly with a relatively small team. It helps us discover the source of the problem, and also can reveal assumptions you or we might be making.
What will happen?
If you've provided a reproduction, we'll remove the label and try to reproduce the issue. If we can, we'll mark it as a bug and prioritize it based on its severity and how many people we think it might affect.
If needs reproduction labeled issues don't receive any substantial activity (e.g., new comments featuring a reproduction link), we'll close them. That's not because we don't care! At any point, feel free to comment with a reproduction and we'll reopen it.
How can I create a reproduction?
We have a couple of templates for starting with a minimal reproduction:
👉 https://stackblitz.com/github/nuxt/starter/tree/v3-stackblitz 👉 https://codesandbox.io/s/github/nuxt/starter/v3-codesandbox
A public GitHub repository is also perfect. 👌
Please ensure that the reproduction is as minimal as possible. See more details in our guide.
You might also find these other articles interesting and/or helpful:
However, when
useRouteis called outside a page context(...)
@danielroe is there any workaround available right now? Cause it prevents us from upgrading from 3.11. Passing route from page component is DX downgrade, as functions inside store calls other functions thus route should be passed multiple times. Prior to 3.12 it was working fine.
However, when
useRouteis called outside a page context(...)@danielroe is there any workaround available right now? Cause it prevents us from upgrading from 3.11. Passing route from page component is DX downgrade, as functions inside store calls other functions thus route should be passed multiple times. Prior to 3.12 it was working fine.
You can try to use my usePageRoute method from different issue.
https://github.com/nuxt/nuxt/issues/24942#issuecomment-1895586730
Works like a charm for us
However, when
useRouteis called outside a page context(...)@danielroe is there any workaround available right now? Cause it prevents us from upgrading from 3.11. Passing route from page component is DX downgrade, as functions inside store calls other functions thus route should be passed multiple times. Prior to 3.12 it was working fine.
You can try to use my usePageRoute method from different issue.
Works like a charm for us
@daniluk4000 this is quite nice, however it introduces another constraint - usePageRoute() triggers route.query watcher before onUnmounted, while useRoute() doesn't in page component.
Just wondering what has changed from 3.11.2 to 3.12.0 that caused this.
That is true, yeah. We use this method for edge cases, but it's not a replacement for regular route sadly.
This could probably be solved in pinia Nuxt module by calling actions with root Vue context rather than component context. I think the current behaviour on the Nuxt end is correct.
This could probably be solved in pinia Nuxt module by calling actions with root Vue context rather than component context. I think the current behaviour on the Nuxt end is correct.
(As I were investigating this, I couldn't find anything that could be done on Nuxt side)
I think the current behaviour on the Nuxt end is correct.
Yet prior to Nuxt 3.12 it was working differently and this issue is marked as bug. Just trying to decide what to do now - is this going to be fixed or should we adapt our app to new behavior?
I am having the same issue in Nuxt 3.11.1. For me it was working fine till 3.11.0.
Just trying to decide what to do now - is this going to be fixed or should we adapt our app to new behavior?
I have the same question.
@mkierdev please let me know if you find a solution...
Encountered the same issue working with nuxt 3.13.1, in some cases the content were updated, some others not. So I had to use the window.location.replace for client side when the NuxtLink wasn't working. I hope this is just a 'temporary fix'
@danielroe Are there any updates on this? Should we use useRoute() only in pages components (what for non-pages components, utilites etc)? Currently this issue locks us on nuxt 3.11 and vue 3.4 and we are still wondering how should we approach this.
Possible workaround: We've refactored our code to pass useRoute() from page components, so now our app is working fine with Suspense components.
We are also encountering an issue where, after a hard page refresh, the query parameters are not being updated when the user sets them. @danielroe when will fix this issue?
@manafatech that doesn't sound like the same issue, which is a bug related to pinia
Hello,
If that helps, I've made a minimal StackBlitz reproduction of the original issue: you can find it here. The issue is triggered when navigating to the page using defineNuxtComponent.
Basically in our project the issue only happened in pages using defineNuxtComponentbut we relied it to be able to run async setup functions where we needed the Nuxt context.
So here's what we did:
- Made sure all our component were using
defineNuxtComponent(for consistency) - We made a composable
useCurrentRoutethat replacesuseRoute, so we can remove it easily later once this is fixed
// composables/useCurrentRoute.ts
export default function () {
return useRouter().currentRoute.value
}
Another possible workaround:
Calling useRoute() not in the beginning of the store but inside the functions once they are called solved the problem for us
Tested workaround mentioned here
import { useRoute as useNativeRoute } from 'vue-router'
const nativeRoute = useNativeRoute()
Working for me with Nuxt 3.7.3
We have the same problem, initially we tried @BBoehm solution which didn't seem to work (we run it in runOnce() function, but the @michael-scheurer workaround worked for use as well.
"nuxt": "3.15.4"
It is crazy that this used to work prior to 3.11.2. I use useRoute() is a lot of components like <Header /> or <Nav /> which sits outside of <NuxtPage /> in a layout file.
What changed?
this should have been resolved in https://github.com/nuxt/nuxt/pull/24673.