T
TanStack3w ago
harsh-harlequin

Relative paths when from path is condition/unknown

In my app I have a pretty complex routing system in place to handle various cases of navigation. I have the following routes that all basically point to the same outlet, just with varying parameters. For example: - The "root" being /catalog: This means the user is viewing their own catalog, but at the root, not within any folder or item - A folder, being /catalog/folder/$folderId: This means the user is viewing their own catalog, within a specific folder - An item at root /catalog/item/$itemId: This means the user is viewing an item within the root of their own catalog - An item within a folder /catalog/folder/$folderId/item/$itemId: This means the user is viewing an item within a folder of their catalog On top of all these, the user could be viewing folders or items within another catalog in which case we end up with /catalog/$catalogId, along with any item or folder suffixes mentioned above. I'm now encountering an interesting problem. When viewing an item, I need to navigate to the proper item, maintaining the current route path. So if i'm on /catalog and navigate to an item, i end up on /catalog/item/$itemId, but if I was within a folder, that has to be /catalog/folder/$folderId/item/$itemId. How does one do this in Tanstack Router?
1 Reply
rising-crimson
rising-crimson2w ago
You can use relative routing based on your from route. So one option for this is something like
<Link from="catalog" to="./item/$itemId" ...rest />
<Link from="catalog/folder/$folderId" to="./item/$itemId" ...rest />
<Link from="catalog" to="./item/$itemId" ...rest />
<Link from="catalog/folder/$folderId" to="./item/$itemId" ...rest />
I'm not sure on the "best" way to get your from to be dynamic, if it's the same component on multiple routes, one option would be something like
const possibleRoutes = [
"catalog",
"catalog/folder/$folderId"
] as const;

const isKnownRoute = (to): to is keyof possibleRoutes => {
return possibleRoutes.includes(to);
}

const from = useMatches({
select: (matches) => {
const to = matches.at(-1)!.routeTo
if (!isKnownRoute(to)
throw new Error("oops");
return to;
}
})
const possibleRoutes = [
"catalog",
"catalog/folder/$folderId"
] as const;

const isKnownRoute = (to): to is keyof possibleRoutes => {
return possibleRoutes.includes(to);
}

const from = useMatches({
select: (matches) => {
const to = matches.at(-1)!.routeTo
if (!isKnownRoute(to)
throw new Error("oops");
return to;
}
})
Someone else may have a better answer

Did you find this page helpful?