Skip to content

Commit 9e386f5

Browse files
fix: reset actionData state on redirection from an action (#9334)
* fix: reset actionData state on redirection from an action * Update contributors.yml * use destination location and add unit test * Update changelog + comments Co-authored-by: Matt Brophy <[email protected]>
1 parent 0a00110 commit 9e386f5

File tree

4 files changed

+87
-5
lines changed

4 files changed

+87
-5
lines changed

.changeset/short-hats-peel.md

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+
fix: reset `actionData` after successful action redirect (#9334)

contributors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
- jmargeta
5555
- johnpangalos
5656
- jonkoops
57+
- jrakotoharisoa
5758
- kantuni
5859
- kddnewton
5960
- kentcdodds

packages/router/__tests__/router-test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,81 @@ describe("a router", () => {
27062706
expect(t.router.state.actionData).toBeNull();
27072707
});
27082708

2709+
it("removes action data after action redirect (w/o loaders to run)", async () => {
2710+
let t = setup({
2711+
routes: [
2712+
{
2713+
index: true,
2714+
id: "index",
2715+
action: true,
2716+
},
2717+
{
2718+
path: "/other",
2719+
id: "other",
2720+
},
2721+
],
2722+
});
2723+
let A = await t.navigate("/", {
2724+
formMethod: "post",
2725+
formData: createFormData({ gosh: "" }),
2726+
});
2727+
await A.actions.index.resolve({ error: "invalid" });
2728+
expect(t.router.state.actionData).toEqual({
2729+
index: { error: "invalid" },
2730+
});
2731+
2732+
let B = await t.navigate("/", {
2733+
formMethod: "post",
2734+
formData: createFormData({ gosh: "dang" }),
2735+
});
2736+
await B.actions.index.redirectReturn("/other");
2737+
2738+
expect(t.router.state.actionData).toBeNull();
2739+
});
2740+
2741+
it("removes action data after action redirect (w/ loaders to run)", async () => {
2742+
let t = setup({
2743+
routes: [
2744+
{
2745+
index: true,
2746+
id: "index",
2747+
action: true,
2748+
},
2749+
{
2750+
path: "/other",
2751+
id: "other",
2752+
loader: true,
2753+
},
2754+
],
2755+
});
2756+
let A = await t.navigate("/", {
2757+
formMethod: "post",
2758+
formData: createFormData({ gosh: "" }),
2759+
});
2760+
await A.actions.index.resolve({ error: "invalid" });
2761+
expect(t.router.state.actionData).toEqual({
2762+
index: { error: "invalid" },
2763+
});
2764+
2765+
let B = await t.navigate("/", {
2766+
formMethod: "post",
2767+
formData: createFormData({ gosh: "dang" }),
2768+
});
2769+
2770+
let C = await B.actions.index.redirectReturn("/other");
2771+
expect(t.router.state.actionData).toEqual({
2772+
index: { error: "invalid" },
2773+
});
2774+
expect(t.router.state.loaderData).toEqual({});
2775+
2776+
await C.loaders.other.resolve("OTHER");
2777+
2778+
expect(t.router.state.actionData).toBeNull();
2779+
expect(t.router.state.loaderData).toEqual({
2780+
other: "OTHER",
2781+
});
2782+
});
2783+
27092784
it("uses the proper action for index routes", async () => {
27102785
let t = setup({
27112786
routes: [

packages/router/router.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -660,14 +660,15 @@ export function createRouter(init: RouterInit): Router {
660660
// - We have committed actionData in the store
661661
// - The current navigation was a submission
662662
// - We're past the submitting state and into the loading state
663-
// - This should not be susceptible to false positives for
664-
// loading/submissionRedirect since there would not be actionData in the
665-
// state since the prior action would have returned a redirect response
666-
// and short circuited
663+
// - The location we've finished loading is different from the submission
664+
// location, indicating we redirected from the action (avoids false
665+
// positives for loading/submissionRedirect when actionData returned
666+
// on a prior submission)
667667
let isActionReload =
668668
state.actionData != null &&
669669
state.navigation.formMethod != null &&
670-
state.navigation.state === "loading";
670+
state.navigation.state === "loading" &&
671+
state.navigation.formAction?.split("?")[0] === location.pathname;
671672

672673
// Always preserve any existing loaderData from re-used routes
673674
let newLoaderData = newState.loaderData

0 commit comments

Comments
 (0)