diff --git a/.changeset/cyan-poems-clean.md b/.changeset/cyan-poems-clean.md new file mode 100644 index 000000000..567cdf9f4 --- /dev/null +++ b/.changeset/cyan-poems-clean.md @@ -0,0 +1,6 @@ +--- +"react-router-dom": patch +"@remix-run/router": patch +--- + +properly support index routes with a path in useResolvedPath diff --git a/packages/react-router-dom/__tests__/data-browser-router-test.tsx b/packages/react-router-dom/__tests__/data-browser-router-test.tsx index aeffc33c1..a8b68ecb8 100644 --- a/packages/react-router-dom/__tests__/data-browser-router-test.tsx +++ b/packages/react-router-dom/__tests__/data-browser-router-test.tsx @@ -1737,6 +1737,29 @@ function testDomRouter( await new Promise((r) => setTimeout(r, 0)); assertLocation(testWindow, "/form", "?index"); }); + + it("handles index routes with a path", async () => { + let { container } = render( + + + + } + /> + + + + ); + + expect(container.querySelector("form")?.getAttribute("action")).toBe( + "/foo/bar?index&a=1#hash" + ); + }); }); describe("dynamic routes", () => { diff --git a/packages/react-router/lib/hooks.tsx b/packages/react-router/lib/hooks.tsx index 76350418a..5909e76fd 100644 --- a/packages/react-router/lib/hooks.tsx +++ b/packages/react-router/lib/hooks.tsx @@ -19,6 +19,7 @@ import { parsePath, resolveTo, warning, + UNSAFE_getPathContributingMatches as getPathContributingMatches, } from "@remix-run/router"; import type { @@ -147,36 +148,6 @@ export interface NavigateFunction { (delta: number): void; } -/** - * When processing relative navigation we want to ignore ancestor routes that - * do not contribute to the path, such that index/pathless layout routes don't - * interfere. - * - * For example, when moving a route element into an index route and/or a - * pathless layout route, relative link behavior contained within should stay - * the same. Both of the following examples should link back to the root: - * - * - * - * - * - * - * - * }> // <-- Does not contribute - * // <-- Does not contribute - * - * - */ -function getPathContributingMatches(matches: RouteMatch[]) { - return matches.filter( - (match, index) => - index === 0 || - (!match.route.index && - match.pathnameBase !== matches[index - 1].pathnameBase) - ); -} - /** * Returns an imperative method for changing the location. Used by s, but * may also be used by other elements to change the location. diff --git a/packages/router/index.ts b/packages/router/index.ts index 4196adc3f..f9739ba56 100644 --- a/packages/router/index.ts +++ b/packages/router/index.ts @@ -1,4 +1,4 @@ -import { convertRoutesToDataRoutes } from "./utils"; +import { convertRoutesToDataRoutes, getPathContributingMatches } from "./utils"; export type { ActionFunction, @@ -79,4 +79,7 @@ export * from "./router"; /////////////////////////////////////////////////////////////////////////////// /** @internal */ -export { convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes }; +export { + convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, + getPathContributingMatches as UNSAFE_getPathContributingMatches, +}; diff --git a/packages/router/utils.ts b/packages/router/utils.ts index 308901d5a..70761f614 100644 --- a/packages/router/utils.ts +++ b/packages/router/utils.ts @@ -857,6 +857,8 @@ function getInvalidPathError( } /** + * @private + * * When processing relative navigation we want to ignore ancestor routes that * do not contribute to the path, such that index/pathless layout routes don't * interfere. @@ -882,9 +884,7 @@ export function getPathContributingMatches< >(matches: T[]) { return matches.filter( (match, index) => - index === 0 || - (!match.route.index && - match.pathnameBase !== matches[index - 1].pathnameBase) + index === 0 || (match.route.path && match.route.path.length > 0) ); }