diff --git a/.changeset/smooth-ligers-give.md b/.changeset/smooth-ligers-give.md
new file mode 100644
index 0000000000..32585404c6
--- /dev/null
+++ b/.changeset/smooth-ligers-give.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/router": patch
+---
+
+De-dup relative path logic in `resolveTo`
diff --git a/package.json b/package.json
index 2686e5942e..53338bc823 100644
--- a/package.json
+++ b/package.json
@@ -110,7 +110,7 @@
},
"filesize": {
"packages/router/dist/router.umd.min.js": {
- "none": "50.2 kB"
+ "none": "50.0 kB"
},
"packages/react-router/dist/react-router.production.min.js": {
"none": "14.6 kB"
diff --git a/packages/router/utils.ts b/packages/router/utils.ts
index bc9a4b211b..a8c35d9595 100644
--- a/packages/router/utils.ts
+++ b/packages/router/utils.ts
@@ -1209,37 +1209,16 @@ export function resolveTo(
// to the current location's pathname and *not* the route pathname.
if (toPathname == null) {
from = locationPathname;
- } else if (isPathRelative) {
- let fromSegments =
- routePathnames.length === 0
- ? []
- : routePathnames[routePathnames.length - 1]
- .replace(/^\//, "")
- .split("/");
-
- if (toPathname.startsWith("..")) {
- let toSegments = toPathname.split("/");
-
- // With relative="path", each leading .. segment means "go up one URL segment"
- while (toSegments[0] === "..") {
- toSegments.shift();
- fromSegments.pop();
- }
-
- to.pathname = toSegments.join("/");
- }
-
- from = "/" + fromSegments.join("/");
} else {
let routePathnameIndex = routePathnames.length - 1;
- if (toPathname.startsWith("..")) {
+ // With relative="route" (the default), each leading .. segment means
+ // "go up one route" instead of "go up one URL segment". This is a key
+ // difference from how works and a major reason we call this a
+ // "to" value instead of a "href".
+ if (!isPathRelative && toPathname.startsWith("..")) {
let toSegments = toPathname.split("/");
- // With relative="route" (the default), each leading .. segment means
- // "go up one route" instead of "go up one URL segment". This is a key
- // difference from how works and a major reason we call this a
- // "to" value instead of a "href".
while (toSegments[0] === "..") {
toSegments.shift();
routePathnameIndex -= 1;
@@ -1248,8 +1227,6 @@ export function resolveTo(
to.pathname = toSegments.join("/");
}
- // If there are more ".." segments than parent routes, resolve relative to
- // the root / URL.
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
}