nuxt icon indicating copy to clipboard operation
nuxt copied to clipboard

useRoute() does not update with current route after upgrading from 3.11.2 to 3.12.0

Open mkierdev opened this issue 1 year ago • 23 comments

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

mkierdev avatar Sep 03 '24 12:09 mkierdev

what's happening if you run testFunctionWithUseRouteInside() on "onMounted()" lifecycle?

fishDev94 avatar Sep 03 '24 13:09 fishDev94

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

mkierdev avatar Sep 03 '24 13:09 mkierdev

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

fishDev94 avatar Sep 03 '24 14:09 fishDev94

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..

mkierdev avatar Sep 03 '24 14:09 mkierdev

but the previous route is not destroyed yet at this point i would say

fishDev94 avatar Sep 03 '24 14:09 fishDev94

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

danielroe avatar Sep 03 '24 21:09 danielroe

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:

github-actions[bot] avatar Sep 03 '24 21:09 github-actions[bot]

However, when useRoute is 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.

mkierdev avatar Sep 05 '24 10:09 mkierdev

However, when useRoute is 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

daniluk4000 avatar Sep 05 '24 10:09 daniluk4000

However, when useRoute is 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.

#24942 (comment)

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.

mkierdev avatar Sep 05 '24 12:09 mkierdev

That is true, yeah. We use this method for edge cases, but it's not a replacement for regular route sadly.

daniluk4000 avatar Sep 05 '24 13:09 daniluk4000

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.

danielroe avatar Sep 05 '24 13:09 danielroe

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)

daniluk4000 avatar Sep 05 '24 13:09 daniluk4000

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?

mkierdev avatar Sep 05 '24 13:09 mkierdev

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.

avi-agg avatar Sep 06 '24 10:09 avi-agg

@mkierdev please let me know if you find a solution...

avi-agg avatar Sep 06 '24 10:09 avi-agg

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'

MauroGonzalez51 avatar Sep 07 '24 20:09 MauroGonzalez51

@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.

mkierdev avatar Sep 16 '24 09:09 mkierdev

Possible workaround: We've refactored our code to pass useRoute() from page components, so now our app is working fine with Suspense components.

mkierdev avatar Sep 17 '24 11:09 mkierdev

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 avatar Oct 10 '24 10:10 manafatech

@manafatech that doesn't sound like the same issue, which is a bug related to pinia

danielroe avatar Oct 10 '24 10:10 danielroe

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 useCurrentRoute that replaces useRoute, so we can remove it easily later once this is fixed
// composables/useCurrentRoute.ts

export default function () {
  return useRouter().currentRoute.value
}

AcelisWeaven avatar Oct 10 '24 13:10 AcelisWeaven

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

BBoehm avatar Oct 11 '24 14:10 BBoehm

Tested workaround mentioned here

import { useRoute as useNativeRoute } from 'vue-router'

const nativeRoute = useNativeRoute()

Working for me with Nuxt 3.7.3

michael-scheurer avatar Feb 06 '25 13:02 michael-scheurer

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"

tux2nicolae avatar Feb 21 '25 22:02 tux2nicolae

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?

richgcook avatar Jun 09 '25 15:06 richgcook

this should have been resolved in https://github.com/nuxt/nuxt/pull/24673.

danielroe avatar Jun 10 '25 09:06 danielroe

this should have been resolved in #24673.

Impressive, TYSM!

daniluk4000 avatar Jun 10 '25 09:06 daniluk4000