-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Which project does this relate to?
Router
Describe the bug
I have the exact route structure shown in the reproduction stackblitz.
I have this Breadcrumbs component (you can see it in the repo Blitzstack, it's based on the one from the kitchensink example)
import { isMatch, Link, useMatches } from '@tanstack/react-router';
export const Breadcrumbs = () => {
const matches = useMatches();
if (matches.some((match) => match.status === 'pending')) {
return null;
}
console.log('matches', matches);
const matchesWithCrumbs = matches.filter((match) => {
return isMatch(match, 'context.crumb');
});
console.log('matchesWithCrumbs', matchesWithCrumbs);
return (
<nav className="grow">
<ul className="flex items-center gap-2">
{matchesWithCrumbs.map((match, i) => {
console.log('match.fullPath', match.fullPath);
console.log('match.params', match.params);
return (
<li key={match.id} className="flex gap-2 items-center">
<div>
{i + 1 < matchesWithCrumbs.length ? (
<Link
className="text-blue-700"
to={match.fullPath}
params={match.params}
>
{match.context.crumb}
</Link>
) : (
match.context.crumb
)}
</div>
{i + 1 < matchesWithCrumbs.length ? '>' : null}
</li>
);
})}
</ul>
</nav>
);
};I get this Typescript error on the Link's to prop:
The type of match shows up as this:
As you can see in the type of the possible fullPaths there is a "" that should not be there and it makes passing the match.fullPath throw cause it sees an unexpected route. This is not visible in the stackblitz editor, because the TS linting is off (the fullPath shows as any), but you can see it if you run it in a properly setup environment.
These are all the matching routes when we run useMatches
[
{
"id": "__root__",
"index": 0,
"routeId": "__root__",
"params": {
"id": "1"
},
"_strictParams": {},
"pathname": "/",
"updatedAt": 1754684906716,
"search": {},
"_strictSearch": {},
"status": "success",
"isFetching": "loader",
"__routeContext": {},
"context": {},
"abortController": {},
"fetchCount": 9,
"cause": "stay",
"loaderDeps": "",
"invalid": false,
"preload": false,
"staticData": {},
"loadPromise": {
"status": "resolved"
},
"fullPath": "/",
"globalNotFound": false,
"loaderPromise": {
"status": "resolved"
}
},
{
"id": "/_authenticated",
"index": 1,
"routeId": "/_authenticated",
"params": {
"id": "1"
},
"_strictParams": {},
"pathname": "/",
"updatedAt": 1754684913726,
"search": {},
"_strictSearch": {},
"status": "success",
"isFetching": "loader",
"__routeContext": {},
"__beforeLoadContext": {
"crumb": "crumb 1"
},
"context": {
"crumb": "crumb 1"
},
"abortController": {},
"fetchCount": 4,
"cause": "enter",
"loaderDeps": "",
"invalid": false,
"preload": false,
"staticData": {},
"loadPromise": {
"status": "resolved"
},
"fullPath": "/",
"loaderPromise": {
"status": "resolved"
},
"globalNotFound": false
},
{
"id": "/_authenticated/something/1/",
"index": 2,
"routeId": "/_authenticated/something/$id/",
"params": {
"id": "1"
},
"_strictParams": {
"id": "1"
},
"pathname": "/something/1/",
"updatedAt": 1754684913726,
"search": {},
"_strictSearch": {},
"status": "success",
"isFetching": "loader",
"__routeContext": {},
"__beforeLoadContext": {
"crumb": "crumb 2"
},
"context": {
"crumb": "crumb 2"
},
"abortController": {},
"fetchCount": 4,
"cause": "enter",
"loaderDeps": "",
"invalid": false,
"preload": false,
"staticData": {},
"loadPromise": {
"status": "resolved"
},
"fullPath": "/something/$id/",
"loaderPromise": {
"status": "resolved"
},
"globalNotFound": false
}
]As you can see for /_authenticated the fullPath is "/"
Your Example Website or App
Steps to Reproduce the Bug or Issue
Try to pass the match.fullPath as value to Link's to prop
Expected behavior
The possible types for match.fullpath should not include an empty ""
Screenshots or Videos
No response
Platform
- Router / Start Version: [e.g. 1.130.10]
- OS: Linux
- Browser: Chrome
- Browser Version: 138.0.7204.92
- Bundler: vite
- Bundler Version: 7.0.6
Additional context
No response