Skip to content

Commit 0211503

Browse files
committed
Do not short circuit on hash change only mutation submissions
1 parent 1143652 commit 0211503

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/router": patch
3+
---
4+
5+
Do not short circuit on hash change only mutation submissions

packages/router/__tests__/router-test.ts

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -819,63 +819,48 @@ const TASK_ROUTES: TestRouteObject[] = [
819819
},
820820
];
821821

822-
const TM_ROUTES = [
822+
const TM_ROUTES: TestRouteObject[] = [
823823
{
824824
path: "",
825825
id: "root",
826-
827-
module: "",
828826
hasErrorBoundary: true,
829827
loader: true,
830828
children: [
831829
{
832830
path: "/",
833831
id: "index",
834-
hasLoader: true,
835832
loader: true,
836833
action: true,
837-
838-
module: "",
839834
},
840835
{
841836
path: "/foo",
842837
id: "foo",
843838
loader: true,
844839
action: true,
845-
846-
module: "",
847840
},
848841
{
849842
path: "/foo/bar",
850843
id: "foobar",
851844
loader: true,
852845
action: true,
853-
854-
module: "",
855846
},
856847
{
857848
path: "/bar",
858849
id: "bar",
859850
loader: true,
860851
action: true,
861-
862-
module: "",
863852
},
864853
{
865854
path: "/baz",
866855
id: "baz",
867856
loader: true,
868857
action: true,
869-
870-
module: "",
871858
},
872859
{
873860
path: "/p/:param",
874861
id: "param",
875862
loader: true,
876863
action: true,
877-
878-
module: "",
879864
},
880865
],
881866
},
@@ -1380,14 +1365,69 @@ describe("a router", () => {
13801365
});
13811366
});
13821367

1383-
it("does not load anything on hash change only", async () => {
1368+
it("does not load anything on hash change only <Link> navigations", async () => {
13841369
let t = initializeTmTest();
13851370
expect(t.router.state.loaderData).toMatchObject({ root: "ROOT" });
13861371
let A = await t.navigate("/#bar");
13871372
expect(A.loaders.root.stub.mock.calls.length).toBe(0);
13881373
expect(t.router.state.loaderData).toMatchObject({ root: "ROOT" });
13891374
});
13901375

1376+
it('does not load anything on hash change only empty <Form method="get"> navigations', async () => {
1377+
let t = initializeTmTest();
1378+
expect(t.router.state.loaderData).toMatchObject({ root: "ROOT" });
1379+
let A = await t.navigate("/#bar", {
1380+
formData: createFormData({}),
1381+
});
1382+
expect(A.loaders.root.stub.mock.calls.length).toBe(0);
1383+
expect(t.router.state.loaderData).toMatchObject({ root: "ROOT" });
1384+
});
1385+
1386+
it('runs loaders on hash change only non-empty <Form method="get"> navigations', async () => {
1387+
let t = initializeTmTest();
1388+
expect(t.router.state.loaderData).toMatchObject({ root: "ROOT" });
1389+
debugger;
1390+
let A = await t.navigate("/#bar", {
1391+
formData: createFormData({ key: "value" }),
1392+
});
1393+
await A.loaders.root.resolve("ROOT 2");
1394+
await A.loaders.index.resolve("INDEX 2");
1395+
expect(t.router.state.location.search).toBe("?key=value");
1396+
expect(t.router.state.loaderData).toMatchObject({
1397+
root: "ROOT 2",
1398+
index: "INDEX 2",
1399+
});
1400+
});
1401+
1402+
it('runs action/loaders on hash change only <Form method="post"> navigations', async () => {
1403+
let t = initializeTmTest();
1404+
let A = await t.navigate("/foo#bar");
1405+
expect(t.router.state.navigation.state).toBe("loading");
1406+
await A.loaders.foo.resolve("A");
1407+
expect(t.router.state.loaderData).toMatchObject({
1408+
root: "ROOT",
1409+
foo: "A",
1410+
});
1411+
1412+
// Submit while we have an active hash causing us to lose it
1413+
let B = await t.navigate("/foo", {
1414+
formMethod: "post",
1415+
formData: createFormData({}),
1416+
});
1417+
expect(t.router.state.navigation.state).toBe("submitting");
1418+
await B.actions.foo.resolve("ACTION");
1419+
await B.loaders.root.resolve("ROOT 2");
1420+
await B.loaders.foo.resolve("B");
1421+
expect(t.router.state.navigation.state).toBe("idle");
1422+
expect(t.router.state.actionData).toMatchObject({
1423+
foo: "ACTION",
1424+
});
1425+
expect(t.router.state.loaderData).toMatchObject({
1426+
root: "ROOT 2",
1427+
foo: "B",
1428+
});
1429+
});
1430+
13911431
it("sets all right states on hash change only", async () => {
13921432
let t = initializeTmTest();
13931433
let key = t.router.state.location.key;
@@ -2396,7 +2436,6 @@ describe("a router", () => {
23962436
children: expect.any(Array),
23972437
id: "root",
23982438
loader: expect.any(Function),
2399-
module: "",
24002439
path: "",
24012440
},
24022441
},
@@ -2473,7 +2512,6 @@ describe("a router", () => {
24732512
children: expect.any(Array),
24742513
id: "root",
24752514
loader: expect.any(Function),
2476-
module: "",
24772515
path: "",
24782516
},
24792517
},

packages/router/router.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,8 +1121,13 @@ export function createRouter(init: RouterInit): Router {
11211121
return;
11221122
}
11231123

1124-
// Short circuit if it's only a hash change
1125-
if (isHashChangeOnly(state.location, location)) {
1124+
// Short circuit if it's only a hash change and not a mutation submission
1125+
// For example, on /page#hash and submit a <Form method="post"> which will
1126+
// default to a navigation to /page
1127+
if (
1128+
isHashChangeOnly(state.location, location) &&
1129+
!(opts && opts.submission && isMutationMethod(opts.submission.formMethod))
1130+
) {
11261131
completeNavigation(location, { matches });
11271132
return;
11281133
}

0 commit comments

Comments
 (0)