Skip to content

Commit 39854ce

Browse files
authored
Fix useAcrtionData so it only returns the contextual route action data (#11023)
1 parent 811e9aa commit 39854ce

File tree

4 files changed

+64
-58
lines changed

4 files changed

+64
-58
lines changed

.changeset/fix-action-data.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
Fix `useActionData` so it returns proper contextual action data and not _any_ action data in the tree

packages/react-router-dom/__tests__/data-browser-router-test.tsx

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ function testDomRouter(
186186
"<div>
187187
<div>
188188
parent data
189-
child action
190189
idle
191190
<div>
192191
child data
@@ -238,7 +237,6 @@ function testDomRouter(
238237
"<div>
239238
<div>
240239
parent data
241-
child action
242240
idle
243241
<div>
244242
child data
@@ -1042,7 +1040,17 @@ function testDomRouter(
10421040
lazy={async () => ({
10431041
action: () => actionDefer.promise,
10441042
loader: () => loaderDefer.promise,
1045-
element: <h1>Action</h1>,
1043+
Component() {
1044+
let data = useLoaderData() as string;
1045+
let actionData = useActionData() as string | undefined;
1046+
return (
1047+
<>
1048+
<h1>Action</h1>
1049+
<p>{data}</p>
1050+
<p>{actionData}</p>
1051+
</>
1052+
);
1053+
},
10461054
})}
10471055
/>
10481056
</Route>
@@ -1054,8 +1062,6 @@ function testDomRouter(
10541062
let { container } = render(<RouterProvider router={router} />);
10551063

10561064
function Home() {
1057-
let data = useMatches().pop()?.data as string | undefined;
1058-
let actionData = useActionData() as string | undefined;
10591065
let navigation = useNavigation();
10601066
let submit = useSubmit();
10611067
let formRef = React.useRef<HTMLFormElement>(null);
@@ -1067,8 +1073,6 @@ function testDomRouter(
10671073
<button onClick={() => submit(formRef.current)}>Submit Form</button>
10681074
<div id="output">
10691075
<p>{navigation.state}</p>
1070-
<p>{data}</p>
1071-
<p>{actionData}</p>
10721076
<Outlet />
10731077
</div>
10741078
</div>
@@ -1084,8 +1088,6 @@ function testDomRouter(
10841088
<p>
10851089
idle
10861090
</p>
1087-
<p />
1088-
<p />
10891091
<h1>
10901092
Home
10911093
</h1>
@@ -1102,8 +1104,6 @@ function testDomRouter(
11021104
<p>
11031105
submitting
11041106
</p>
1105-
<p />
1106-
<p />
11071107
<h1>
11081108
Home
11091109
</h1>
@@ -1120,10 +1120,6 @@ function testDomRouter(
11201120
<p>
11211121
loading
11221122
</p>
1123-
<p />
1124-
<p>
1125-
Action Data
1126-
</p>
11271123
<h1>
11281124
Home
11291125
</h1>
@@ -1140,15 +1136,15 @@ function testDomRouter(
11401136
<p>
11411137
idle
11421138
</p>
1139+
<h1>
1140+
Action
1141+
</h1>
11431142
<p>
11441143
Loader Data
11451144
</p>
11461145
<p>
11471146
Action Data
11481147
</p>
1149-
<h1>
1150-
Action
1151-
</h1>
11521148
</div>"
11531149
`);
11541150
});
@@ -1264,7 +1260,17 @@ function testDomRouter(
12641260
).searchParams.get("test");
12651261
return `${resolvedValue}:${urlParam}`;
12661262
},
1267-
element: <h1>Path</h1>,
1263+
Component() {
1264+
let data = useLoaderData() as string;
1265+
let actionData = useActionData() as string | undefined;
1266+
return (
1267+
<>
1268+
<h1>Path</h1>
1269+
<p>{data}</p>
1270+
<p>{actionData}</p>
1271+
</>
1272+
);
1273+
},
12681274
})}
12691275
/>
12701276
</Route>
@@ -1276,8 +1282,6 @@ function testDomRouter(
12761282
let { container } = render(<RouterProvider router={router} />);
12771283

12781284
function Home() {
1279-
let data = useMatches().pop()?.data as string | undefined;
1280-
let actionData = useActionData() as string | undefined;
12811285
let navigation = useNavigation();
12821286
return (
12831287
<div>
@@ -1287,8 +1291,6 @@ function testDomRouter(
12871291
</Form>
12881292
<div id="output">
12891293
<p>{navigation.state}</p>
1290-
<p>{data}</p>
1291-
<p>{actionData}</p>
12921294
<Outlet />
12931295
</div>
12941296
</div>
@@ -1304,8 +1306,6 @@ function testDomRouter(
13041306
<p>
13051307
idle
13061308
</p>
1307-
<p />
1308-
<p />
13091309
<h1>
13101310
Home
13111311
</h1>
@@ -1322,8 +1322,6 @@ function testDomRouter(
13221322
<p>
13231323
loading
13241324
</p>
1325-
<p />
1326-
<p />
13271325
<h1>
13281326
Home
13291327
</h1>
@@ -1340,13 +1338,13 @@ function testDomRouter(
13401338
<p>
13411339
idle
13421340
</p>
1341+
<h1>
1342+
Path
1343+
</h1>
13431344
<p>
13441345
Loader Data:value
13451346
</p>
13461347
<p />
1347-
<h1>
1348-
Path
1349-
</h1>
13501348
</div>"
13511349
`);
13521350
});
@@ -1477,7 +1475,17 @@ function testDomRouter(
14771475
return `${resolvedValue}:${formData.get("test")}`;
14781476
},
14791477
loader: () => loaderDefer.promise,
1480-
element: <h1>Action</h1>,
1478+
Component() {
1479+
let data = useLoaderData() as string;
1480+
let actionData = useActionData() as string | undefined;
1481+
return (
1482+
<>
1483+
<h1>Action</h1>
1484+
<p>{data}</p>
1485+
<p>{actionData}</p>
1486+
</>
1487+
);
1488+
},
14811489
})}
14821490
/>
14831491
</Route>
@@ -1490,8 +1498,6 @@ function testDomRouter(
14901498
let { container } = render(<RouterProvider router={router} />);
14911499

14921500
function Home() {
1493-
let data = useMatches().pop()?.data as string | undefined;
1494-
let actionData = useActionData() as string | undefined;
14951501
let navigation = useNavigation();
14961502
return (
14971503
<div>
@@ -1501,8 +1507,6 @@ function testDomRouter(
15011507
</Form>
15021508
<div id="output">
15031509
<p>{navigation.state}</p>
1504-
<p>{data}</p>
1505-
<p>{actionData}</p>
15061510
<Outlet />
15071511
</div>
15081512
</div>
@@ -1518,8 +1522,6 @@ function testDomRouter(
15181522
<p>
15191523
idle
15201524
</p>
1521-
<p />
1522-
<p />
15231525
<h1>
15241526
Home
15251527
</h1>
@@ -1536,8 +1538,6 @@ function testDomRouter(
15361538
<p>
15371539
submitting
15381540
</p>
1539-
<p />
1540-
<p />
15411541
<h1>
15421542
Home
15431543
</h1>
@@ -1554,10 +1554,6 @@ function testDomRouter(
15541554
<p>
15551555
loading
15561556
</p>
1557-
<p />
1558-
<p>
1559-
Action Data:value
1560-
</p>
15611557
<h1>
15621558
Home
15631559
</h1>
@@ -1574,15 +1570,15 @@ function testDomRouter(
15741570
<p>
15751571
idle
15761572
</p>
1573+
<h1>
1574+
Action
1575+
</h1>
15771576
<p>
15781577
Loader Data
15791578
</p>
15801579
<p>
15811580
Action Data:value
15821581
</p>
1583-
<h1>
1584-
Action
1585-
</h1>
15861582
</div>"
15871583
`);
15881584
});
@@ -2038,7 +2034,7 @@ function testDomRouter(
20382034
path="1"
20392035
action={() => "action"}
20402036
loader={() => "1"}
2041-
element={<h1>Page 1</h1>}
2037+
element={<Page />}
20422038
/>
20432039
</Route>
20442040
),
@@ -2052,7 +2048,6 @@ function testDomRouter(
20522048
function Layout() {
20532049
let navigate = useNavigate();
20542050
let submit = useSubmit();
2055-
let actionData = useActionData() as string | undefined;
20562051
let formData = new FormData();
20572052
formData.append("test", "value");
20582053
return (
@@ -2067,13 +2062,22 @@ function testDomRouter(
20672062
</button>
20682063
<button onClick={() => navigate(-1)}>Go back</button>
20692064
<div className="output">
2070-
{actionData ? <p>{actionData}</p> : null}
20712065
<Outlet />
20722066
</div>
20732067
</>
20742068
);
20752069
}
20762070

2071+
function Page() {
2072+
let actionData = useActionData() as string | undefined;
2073+
return (
2074+
<>
2075+
<h1>Page 1</h1>
2076+
<p>{actionData}</p>
2077+
</>
2078+
);
2079+
}
2080+
20772081
expect(getHtml(container.querySelector(".output")!))
20782082
.toMatchInlineSnapshot(`
20792083
"<div
@@ -2095,6 +2099,7 @@ function testDomRouter(
20952099
<h1>
20962100
Page 1
20972101
</h1>
2102+
<p />
20982103
</div>"
20992104
`);
21002105

@@ -2105,12 +2110,12 @@ function testDomRouter(
21052110
"<div
21062111
class="output"
21072112
>
2108-
<p>
2109-
action
2110-
</p>
21112113
<h1>
21122114
Page 1
21132115
</h1>
2116+
<p>
2117+
action
2118+
</p>
21142119
</div>"
21152120
`);
21162121

packages/react-router/__tests__/data-memory-router-test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ describe("createMemoryRouter", () => {
295295
"<div>
296296
<div>
297297
parent data
298-
child action
299298
idle
300299
<div>
301300
child data

packages/react-router/lib/hooks.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -879,11 +879,8 @@ export function useRouteLoaderData(routeId: string): unknown {
879879
*/
880880
export function useActionData(): unknown {
881881
let state = useDataRouterState(DataRouterStateHook.UseActionData);
882-
883-
let route = React.useContext(RouteContext);
884-
invariant(route, `useActionData must be used inside a RouteContext`);
885-
886-
return Object.values(state?.actionData || {})[0];
882+
let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
883+
return state.actionData ? state.actionData[routeId] : undefined;
887884
}
888885

889886
/**

0 commit comments

Comments
 (0)