Skip to content

Commit

Permalink
fix: submissions should ignore pathless layout routes (#9455)
Browse files Browse the repository at this point in the history
* fix: submissions should ignore pathless layout routes

* Add changset

* bump bundle threshold
  • Loading branch information
brophdawg11 committed Oct 17, 2022
1 parent 35ff025 commit 71ee40a
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-bulldogs-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/router": patch
---

Ignore pathless layout routes when looking for proper submission action function
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
},
"filesize": {
"packages/router/dist/router.js": {
"none": "100 kB"
"none": "101 kB"
},
"packages/react-router/dist/react-router.production.min.js": {
"none": "12.5 kB"
Expand Down
50 changes: 50 additions & 0 deletions packages/router/__tests__/router-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2859,6 +2859,56 @@ describe("a router", () => {
});
});

it("uses the proper action for pathless layout routes", async () => {
let t = setup({
routes: [
{
id: "parent",
path: "/parent",
action: true,
children: [
{
hasErrorBoundary: true,
children: [
{
id: "index",
index: true,
action: true,
},
],
},
],
},
],
});
debugger;
let A = await t.navigate("/parent", {
formMethod: "post",
formData: createFormData({ gosh: "dang" }),
});
await A.actions.parent.resolve("PARENT");
expect(t.router.state).toMatchObject({
location: { pathname: "/parent" },
actionData: {
parent: "PARENT",
},
errors: null,
});

let B = await t.navigate("/parent?index", {
formMethod: "post",
formData: createFormData({ gosh: "dang" }),
});
await B.actions.index.resolve("INDEX");
expect(t.router.state).toMatchObject({
location: { pathname: "/parent", search: "?index" },
actionData: {
index: "INDEX",
},
errors: null,
});
});

it("retains the index match when submitting to a layout route", async () => {
let t = setup({
routes: [
Expand Down
11 changes: 8 additions & 3 deletions packages/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
ErrorResponse,
ResultType,
convertRoutesToDataRoutes,
getPathContributingMatches,
invariant,
isRouteErrorResponse,
matchRoutes,
Expand Down Expand Up @@ -2838,11 +2839,15 @@ function getTargetMatch(
typeof location === "string" ? parsePath(location).search : location.search;
if (
matches[matches.length - 1].route.index &&
!hasNakedIndexQuery(search || "")
hasNakedIndexQuery(search || "")
) {
return matches.slice(-2)[0];
// Return the leaf index route when index is present
return matches[matches.length - 1];
}
return matches.slice(-1)[0];
// Otherwise grab the deepest "path contributing" match (ignoring index and
// pathless layout routes)
let pathMatches = getPathContributingMatches(matches);
return pathMatches[pathMatches.length - 1];
}

function createURL(location: Location | string): URL {
Expand Down
32 changes: 32 additions & 0 deletions packages/router/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,38 @@ function getInvalidPathError(
);
}

/**
* 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:
*
* <Route path="/">
* <Route path="accounts" element={<Link to=".."}>
* </Route>
*
* <Route path="/">
* <Route path="accounts">
* <Route element={<AccountsLayout />}> // <-- Does not contribute
* <Route index element={<Link to=".."} /> // <-- Does not contribute
* </Route
* </Route>
* </Route>
*/
export function getPathContributingMatches<
T extends AgnosticRouteMatch = AgnosticRouteMatch
>(matches: T[]) {
return matches.filter(
(match, index) =>
index === 0 ||
(!match.route.index &&
match.pathnameBase !== matches[index - 1].pathnameBase)
);
}

/**
* @private
*/
Expand Down

0 comments on commit 71ee40a

Please sign in to comment.