Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auto-imported useRoute() from nuxt requires use of <NuxtPage> #14595

Open
Nyanng opened this issue Aug 15, 2022 · 15 comments
Open

auto-imported useRoute() from nuxt requires use of <NuxtPage> #14595

Nyanng opened this issue Aug 15, 2022 · 15 comments

Comments

@Nyanng
Copy link

Nyanng commented Aug 15, 2022

Environment

  • Operating System: Darwin
  • Node Version: v18.7.0
  • Nuxt Version: 3.0.0-rc.8
  • Package Manager: yarn@1.22.19
  • Builder: vite
  • User Config: modules, css, colorMode, vite, app
  • Runtime Modules: nuxt-windicss@2.5.0, @pinia/nuxt@0.3.1, @nuxtjs/color-mode@3.1.4, @nuxt/image-edge@1.0.0-27657146.da85542
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/github-izskfd?file=components/Book.vue

Describe the bug

useRoute(), nuxt default provided function, has previous route information, and not updated on moving page.

But using import { useRoute } from vue-router, resolve all problems.

Is there any point I missed?

Additional context

rc.6 doesn't have problems but rc.8 has.

It just occurred as soon as updating from rc.6 to rc.8

Logs

No response

@pi0
Copy link
Member

pi0 commented Aug 15, 2022

/cc @danielroe

@Lyokolux
Copy link

Lyokolux commented Aug 16, 2022

I got the same error in #14585 while using useRoute().

It seems it works again after restarting the server a couple time. I can not explain it for now.
Restarting the server after the first cold start was also a workaround for #14585 if it can help.

@danielroe
Copy link
Member

danielroe commented Aug 16, 2022

The key thing is that you should not destructure params from the returned route object that Nuxt (or vue-router) provides, as it is a reactive object and destructuring anything from it causes it to lose reactivity.

- const { params } = useRoute()
+ const route = useRoute()

Once fixed, note that you were effective re-implementing a route that was always one step behind the actual route in app.vue. Here is a working example, with those two issues resolved: https://stackblitz.com/edit/github-izskfd-zzrrtu

@Nyanng
Copy link
Author

Nyanng commented Aug 16, 2022

I want to show Book Componenet with background (previous page), so I edited :route property on <NuxtPage>, still doesn't works route.params.id on Book.vue.

But I add import { useRoute } from 'vue-router' on Book.vue, it does work.

Please let me know where my mistake is...

app.vue:

...

- const route = useRoute();

const routeWithPopup = computed(() =>
+    historyState.value.background ? resolve(historyState.value.background) : undefined
);

...
...
+ <NuxtPage :route="routeWithPopup" />
...

components/Book.vue:

// When I add
// import { useRoute } from 'vue-router'
// It does work

const route = useRoute();
<!-- doesn't work with no import -->
<div>Book {{ route.params.id }}</div>

@themaxsandelin
Copy link

I have the exact same issue. Could also throw in the fact that if I have useFetch depend on route.params it doesn't update the param I use, regardless of if I use the Options API approach or Composition API using the vue-router workaround.

Here's my code examples:

Composition API

<script setup>
  import { useRoute, useRouter } from 'vue-router';
  
  const route = useRoute();
  const { pending, data: pages, refresh } = await useLazyFetch(`/api/sites/${route.params.siteKey}/pages`);

  watch(
    () => route.params.siteKey, async siteKey => {
      refresh();
    }
  );
</script>

Options API

<script type="ts">
  import { defineComponent } from 'vue';

  export default defineComponent({
    async setup() {
      const route = useRoute();
      const { data, refresh: refreshPages } = await useFetch(`/api/sites/${route.params.siteKey}/pages`);

      return {
        pages: data.value,
        refreshPages
      }
    },
    watch: {
      '$route.params.siteKey': function(oldValue, newValue) {
        this.refreshPages();
      }
    }
  });
</script>

In both cases, the watch sees the new value and it is in fact changed. However, the refetch(), or rather useFetch does not pick up the new param and instead uses the previous one, always. So after a second route change, it uses the one from the previous route change.

@danielroe should I open a new issue regarding the useFetch portion of the issue? Or could it be considered the same issue?

@danielroe
Copy link
Member

The issue here is that you should not import useRoute from vue-router but from #imports. We have a custom implementation of useRoute that handles some suspense related issues (nuxt/framework#6275).

The useFetch issue you describe is already covered by #14342.

@themaxsandelin
Copy link

@danielroe Regarding the vue-router import, that is only to make it possible to listen to the route params changing using the Composition API approach as mentioned above. If I don't it doesn't react to any changes, regardless of me listening to the specific param siteKey, all params or the whole route itself.

Thank you for referring me to the other issue regarding useFetch! 🙏

@Ischafak
Copy link

Ischafak commented Oct 25, 2022

|@danielroe hi, in my application i am changing page with NuxtLink and i am using useRoute in footer. when first load the page useRoute data works very well but after i change page fullpath doesnt change. How can i fix this can anyone help me please?

<script setup>
const route = useRoute()

const isPricing = computed(() => {
  return route.fullPath === "/blablabla"
})
</script>

"nuxt": "3.0.0-rc.11",

@BenjaminOddou
Copy link

@Ischafak my workaround (it's not very pretty) is to use state management that will refresh a variable 🤔.

In app.vue
const isLink = linkStore() // I am using pinia
let thisLink: string
isLink.$subscribe(() => {
thisLink = location.href // when the state change thisLink is updated
})

@ValJed
Copy link

ValJed commented Oct 31, 2022

Hi there !
Tiny ping because I'm also experiencing this issue.
Nuxt version 3.0.0-rc.11

Code example:

// experiences/index.js

<template>
  <div>
    <h1>Experiences</h1>
    <ul>
      <li>
        <NuxtLink to="experiences/experience1">
          <div>
            <img src="/images/exp1.png" />
          </div>
        </NuxtLink>
      </li>
      <li>
        <NuxtLink to="experiences/experience2">
          <img src="/images/exp2.png"  />
        </NuxtLink>
      </li>
    </ul>
  </div>
</template>
// experiences/[experience].js
<script setup>
import experiences from '@/data/experiences'
import { useRoute } from 'vue-router' // With this line it's working as expected

const route = useRoute()

const current = route.params.experience // This param is loaded once but never updated while the route changes
const experience = experiences[current] // So this variable always stays the same
</script>

For me too, the only way of making it work is to import manually import { useRoute } from 'vue-router'.
When counting on the auto import it simply doesn't work.

PS: Note that the problem doesn't come, at least in my case, from destructuring.

Thanks!

@chenxch
Copy link

chenxch commented Nov 30, 2022

demo
The built-in useRoute has lost its reactive, which is currently solved by manually introducing the useRoute of vue-router. I think that even if hijacking is required for encapsulation, the consistency of performance should be maintained.

@danielroe
Copy link
Member

danielroe commented Nov 30, 2022

@chenxch The issue you are experiencing is that the built-in useRoute relies on using <NuxtPage>.

@chenxch
Copy link

chenxch commented Nov 30, 2022

@danielroe thx~💗

@kuzroman
Copy link

kuzroman commented Dec 10, 2022

I just added import to composables file for workaraund:

//composables/common.js
import { useRoute as use_Route } from 'vue-router' // workaround bug #14595
export const useRoute = () => use_Route()

//and in components we can use route as usually, they will reactive
//App.vue
const route = useRoute()

@danielroe danielroe added the 3.x label Jan 19, 2023
@danielroe danielroe transferred this issue from nuxt/framework Jan 19, 2023
@danielroe danielroe changed the title useRoute() in 'vue-router' is working but not in nuxt. auto-imported useRoute() from nuxt requires use of <NuxtPage> Mar 6, 2023
@p1xel007
Copy link

I'm facing the same issue, is there any fix available?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests