diff --git a/.changeset/fix-action-data.md b/.changeset/fix-action-data.md new file mode 100644 index 0000000000..376fc7f141 --- /dev/null +++ b/.changeset/fix-action-data.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +Fix `useActionData` so it returns proper contextual action data and not _any_ action data in the tree 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 574b653816..3c96cf2444 100644 --- a/packages/react-router-dom/__tests__/data-browser-router-test.tsx +++ b/packages/react-router-dom/__tests__/data-browser-router-test.tsx @@ -186,7 +186,6 @@ function testDomRouter( "
parent data - child action idle
child data @@ -238,7 +237,6 @@ function testDomRouter( "
parent data - child action idle
child data @@ -1042,7 +1040,17 @@ function testDomRouter( lazy={async () => ({ action: () => actionDefer.promise, loader: () => loaderDefer.promise, - element:

Action

, + Component() { + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; + return ( + <> +

Action

+

{data}

+

{actionData}

+ + ); + }, })} /> @@ -1054,8 +1062,6 @@ function testDomRouter( let { container } = render(); function Home() { - let data = useMatches().pop()?.data as string | undefined; - let actionData = useActionData() as string | undefined; let navigation = useNavigation(); let submit = useSubmit(); let formRef = React.useRef(null); @@ -1067,8 +1073,6 @@ function testDomRouter(

{navigation.state}

-

{data}

-

{actionData}

@@ -1084,8 +1088,6 @@ function testDomRouter(

idle

-

-

Home

@@ -1102,8 +1104,6 @@ function testDomRouter(

submitting

-

-

Home

@@ -1120,10 +1120,6 @@ function testDomRouter(

loading

-

-

- Action Data -

Home

@@ -1140,15 +1136,15 @@ function testDomRouter(

idle

+

+ Action +

Loader Data

Action Data

-

- Action -

" `); }); @@ -1264,7 +1260,17 @@ function testDomRouter( ).searchParams.get("test"); return `${resolvedValue}:${urlParam}`; }, - element:

Path

, + Component() { + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; + return ( + <> +

Path

+

{data}

+

{actionData}

+ + ); + }, })} /> @@ -1276,8 +1282,6 @@ function testDomRouter( let { container } = render(); function Home() { - let data = useMatches().pop()?.data as string | undefined; - let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1287,8 +1291,6 @@ function testDomRouter(

{navigation.state}

-

{data}

-

{actionData}

@@ -1304,8 +1306,6 @@ function testDomRouter(

idle

-

-

Home

@@ -1322,8 +1322,6 @@ function testDomRouter(

loading

-

-

Home

@@ -1340,13 +1338,13 @@ function testDomRouter(

idle

+

+ Path +

Loader Data:value

-

- Path -

" `); }); @@ -1477,7 +1475,17 @@ function testDomRouter( return `${resolvedValue}:${formData.get("test")}`; }, loader: () => loaderDefer.promise, - element:

Action

, + Component() { + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; + return ( + <> +

Action

+

{data}

+

{actionData}

+ + ); + }, })} /> @@ -1490,8 +1498,6 @@ function testDomRouter( let { container } = render(); function Home() { - let data = useMatches().pop()?.data as string | undefined; - let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1501,8 +1507,6 @@ function testDomRouter(

{navigation.state}

-

{data}

-

{actionData}

@@ -1518,8 +1522,6 @@ function testDomRouter(

idle

-

-

Home

@@ -1536,8 +1538,6 @@ function testDomRouter(

submitting

-

-

Home

@@ -1554,10 +1554,6 @@ function testDomRouter(

loading

-

-

- Action Data:value -

Home

@@ -1574,15 +1570,15 @@ function testDomRouter(

idle

+

+ Action +

Loader Data

Action Data:value

-

- Action -

" `); }); @@ -2038,7 +2034,7 @@ function testDomRouter( path="1" action={() => "action"} loader={() => "1"} - element={

Page 1

} + element={} /> ), @@ -2052,7 +2048,6 @@ function testDomRouter( function Layout() { let navigate = useNavigate(); let submit = useSubmit(); - let actionData = useActionData() as string | undefined; let formData = new FormData(); formData.append("test", "value"); return ( @@ -2067,13 +2062,22 @@ function testDomRouter(
- {actionData ?

{actionData}

: null}
); } + function Page() { + let actionData = useActionData() as string | undefined; + return ( + <> +

Page 1

+

{actionData}

+ + ); + } + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
Page 1 +

" `); @@ -2105,12 +2110,12 @@ function testDomRouter( "
-

- action -

Page 1

+

+ action +

" `); diff --git a/packages/react-router/__tests__/data-memory-router-test.tsx b/packages/react-router/__tests__/data-memory-router-test.tsx index 65792421da..6ae0c0ecc5 100644 --- a/packages/react-router/__tests__/data-memory-router-test.tsx +++ b/packages/react-router/__tests__/data-memory-router-test.tsx @@ -295,7 +295,6 @@ describe("createMemoryRouter", () => { "
parent data - child action idle
child data diff --git a/packages/react-router/lib/hooks.tsx b/packages/react-router/lib/hooks.tsx index 897c33d37b..1102fbe571 100644 --- a/packages/react-router/lib/hooks.tsx +++ b/packages/react-router/lib/hooks.tsx @@ -879,11 +879,8 @@ export function useRouteLoaderData(routeId: string): unknown { */ export function useActionData(): unknown { let state = useDataRouterState(DataRouterStateHook.UseActionData); - - let route = React.useContext(RouteContext); - invariant(route, `useActionData must be used inside a RouteContext`); - - return Object.values(state?.actionData || {})[0]; + let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData); + return state.actionData ? state.actionData[routeId] : undefined; } /**