`useRoute.matched` is not returning all matching routes
Environment
- Operating System: Linux
- Node Version: v18.20.3
- Nuxt Version: 3.13.0
- CLI Version: 3.13.0
- Nitro Version: 2.9.7
- Package Manager: [email protected]
- Builder: -
- User Config: compatibilityDate, future, devtools
- Runtime Modules: -
- Build Modules: -
Reproduction
https://stackblitz.com/edit/github-ezruhh?file=app%2Fapp.vue
Describe the bug
With future: { compatibilityVersion: 4:} set in nuxt.config.ts, useRouter.matched is returning only 1 item on dynamic routes, e.g. /app/pages/[id].vue. This is unexpected behavior, as $route.matched should be an array of normalized matched routes with current route location, in this case it should contain two items. This bug breaks components depending on this property, e.g. NuxtLink activeClass stops working for dynamic routes.
Additional context
No response
Logs
No response
This doesn't seem to be related to future.compatibilityVersion. Did you have a version of Nuxt + vue-router that behaves as you expect?
updated repro to show same behaviour on previous version of nuxt/vue-router:
https://stackblitz.com/edit/github-ezruhh-g2prlc
It worked before we changed to future, but as your repro shows, it doesn't seem to be the root cause. We noticed NuxtLink is not working as expected, as activeClass is not triggered on dynamic subroutes like it used to.
We found out why it worked before, it had nothing to do with versions. We had an additional page1.vue in pages, which rendered the index.vue as NuxtPage, something like this:
-| pages/
---| page1/
------| [id].vue
------| index.vue
---| page1.vue
page1.vue
<template>
<NuxtPage />
</template>
With that, $route.matched contains two objects, and NuxtLink works. It's an accidental workaround. However, this is still a bug, as actually there should be 3 matches when looking at the routes:
I'm not sure why this happens, as in general an index.vue in another folder matches as expected, e.g.:
-| pages/
---| page1/
------| [id].vue
------| index.vue
---| page3/
------| index.vue
has one matched route for page3, but also only one matched route for /page1/id, missing page1 as a match.
https://stackblitz.com/edit/github-ezruhh-yr5ch7?file=components%2Fsidebar.vue
I encountered the same issue
Is there any update on this? It's still in triage, I think this should be confirmed as a bug?
Same problem here. I have some URLs matching with the wrong route and then if I return false on the validation function it won't search for more matches since the route.matches has only the current one.
Here's my workaround, simulating what nuxt 2 was doing:
hooks: {
'pages:extend' (routes) {
const routeNameSplitter = '/'
const root = createResolver(import.meta.url).resolve('./pages')
function updateName (rRoutes) {
if (!rRoutes) return
// eslint-disable-next-line no-restricted-syntax
for (const route of rRoutes) {
const aux = route.file.substring(root.length + 1).match(/\(.*?\)/g)
const relativePath = route.file.substring(root.length + 1).replace(/\(.*?\)/g, '')
route.name = relativePath.slice(0, -4)
.replace(/\/index$/, '')
.replace(/\//g, routeNameSplitter)
.replace(/\[\.\.\.all\]/g, 'all')
.replace(/\[(.+?)\]/g, '$1')
// WORKAROUND
if (aux) {
aux.forEach(validParams => {
route.path = route.path
.replace(/\(\)/, validParams)
});
}
// END WORKAROUND
updateName(route.children)
}
}
updateName(routes)
}
}
}