Skip to content

Commit

Permalink
Fix useAcrtionData so it only returns the contextual route action data (
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Nov 14, 2023
1 parent 811e9aa commit 39854ce
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 58 deletions.
5 changes: 5 additions & 0 deletions .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
109 changes: 57 additions & 52 deletions packages/react-router-dom/__tests__/data-browser-router-test.tsx
Expand Up @@ -186,7 +186,6 @@ function testDomRouter(
"<div>
<div>
parent data
child action
idle
<div>
child data
Expand Down Expand Up @@ -238,7 +237,6 @@ function testDomRouter(
"<div>
<div>
parent data
child action
idle
<div>
child data
Expand Down Expand Up @@ -1042,7 +1040,17 @@ function testDomRouter(
lazy={async () => ({
action: () => actionDefer.promise,
loader: () => loaderDefer.promise,
element: <h1>Action</h1>,
Component() {
let data = useLoaderData() as string;
let actionData = useActionData() as string | undefined;
return (
<>
<h1>Action</h1>
<p>{data}</p>
<p>{actionData}</p>
</>
);
},
})}
/>
</Route>
Expand All @@ -1054,8 +1062,6 @@ function testDomRouter(
let { container } = render(<RouterProvider router={router} />);

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<HTMLFormElement>(null);
Expand All @@ -1067,8 +1073,6 @@ function testDomRouter(
<button onClick={() => submit(formRef.current)}>Submit Form</button>
<div id="output">
<p>{navigation.state}</p>
<p>{data}</p>
<p>{actionData}</p>
<Outlet />
</div>
</div>
Expand All @@ -1084,8 +1088,6 @@ function testDomRouter(
<p>
idle
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1102,8 +1104,6 @@ function testDomRouter(
<p>
submitting
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1120,10 +1120,6 @@ function testDomRouter(
<p>
loading
</p>
<p />
<p>
Action Data
</p>
<h1>
Home
</h1>
Expand All @@ -1140,15 +1136,15 @@ function testDomRouter(
<p>
idle
</p>
<h1>
Action
</h1>
<p>
Loader Data
</p>
<p>
Action Data
</p>
<h1>
Action
</h1>
</div>"
`);
});
Expand Down Expand Up @@ -1264,7 +1260,17 @@ function testDomRouter(
).searchParams.get("test");
return `${resolvedValue}:${urlParam}`;
},
element: <h1>Path</h1>,
Component() {
let data = useLoaderData() as string;
let actionData = useActionData() as string | undefined;
return (
<>
<h1>Path</h1>
<p>{data}</p>
<p>{actionData}</p>
</>
);
},
})}
/>
</Route>
Expand All @@ -1276,8 +1282,6 @@ function testDomRouter(
let { container } = render(<RouterProvider router={router} />);

function Home() {
let data = useMatches().pop()?.data as string | undefined;
let actionData = useActionData() as string | undefined;
let navigation = useNavigation();
return (
<div>
Expand All @@ -1287,8 +1291,6 @@ function testDomRouter(
</Form>
<div id="output">
<p>{navigation.state}</p>
<p>{data}</p>
<p>{actionData}</p>
<Outlet />
</div>
</div>
Expand All @@ -1304,8 +1306,6 @@ function testDomRouter(
<p>
idle
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1322,8 +1322,6 @@ function testDomRouter(
<p>
loading
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1340,13 +1338,13 @@ function testDomRouter(
<p>
idle
</p>
<h1>
Path
</h1>
<p>
Loader Data:value
</p>
<p />
<h1>
Path
</h1>
</div>"
`);
});
Expand Down Expand Up @@ -1477,7 +1475,17 @@ function testDomRouter(
return `${resolvedValue}:${formData.get("test")}`;
},
loader: () => loaderDefer.promise,
element: <h1>Action</h1>,
Component() {
let data = useLoaderData() as string;
let actionData = useActionData() as string | undefined;
return (
<>
<h1>Action</h1>
<p>{data}</p>
<p>{actionData}</p>
</>
);
},
})}
/>
</Route>
Expand All @@ -1490,8 +1498,6 @@ function testDomRouter(
let { container } = render(<RouterProvider router={router} />);

function Home() {
let data = useMatches().pop()?.data as string | undefined;
let actionData = useActionData() as string | undefined;
let navigation = useNavigation();
return (
<div>
Expand All @@ -1501,8 +1507,6 @@ function testDomRouter(
</Form>
<div id="output">
<p>{navigation.state}</p>
<p>{data}</p>
<p>{actionData}</p>
<Outlet />
</div>
</div>
Expand All @@ -1518,8 +1522,6 @@ function testDomRouter(
<p>
idle
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1536,8 +1538,6 @@ function testDomRouter(
<p>
submitting
</p>
<p />
<p />
<h1>
Home
</h1>
Expand All @@ -1554,10 +1554,6 @@ function testDomRouter(
<p>
loading
</p>
<p />
<p>
Action Data:value
</p>
<h1>
Home
</h1>
Expand All @@ -1574,15 +1570,15 @@ function testDomRouter(
<p>
idle
</p>
<h1>
Action
</h1>
<p>
Loader Data
</p>
<p>
Action Data:value
</p>
<h1>
Action
</h1>
</div>"
`);
});
Expand Down Expand Up @@ -2038,7 +2034,7 @@ function testDomRouter(
path="1"
action={() => "action"}
loader={() => "1"}
element={<h1>Page 1</h1>}
element={<Page />}
/>
</Route>
),
Expand All @@ -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 (
Expand All @@ -2067,13 +2062,22 @@ function testDomRouter(
</button>
<button onClick={() => navigate(-1)}>Go back</button>
<div className="output">
{actionData ? <p>{actionData}</p> : null}
<Outlet />
</div>
</>
);
}

function Page() {
let actionData = useActionData() as string | undefined;
return (
<>
<h1>Page 1</h1>
<p>{actionData}</p>
</>
);
}

expect(getHtml(container.querySelector(".output")!))
.toMatchInlineSnapshot(`
"<div
Expand All @@ -2095,6 +2099,7 @@ function testDomRouter(
<h1>
Page 1
</h1>
<p />
</div>"
`);

Expand All @@ -2105,12 +2110,12 @@ function testDomRouter(
"<div
class="output"
>
<p>
action
</p>
<h1>
Page 1
</h1>
<p>
action
</p>
</div>"
`);

Expand Down
Expand Up @@ -295,7 +295,6 @@ describe("createMemoryRouter", () => {
"<div>
<div>
parent data
child action
idle
<div>
child data
Expand Down
7 changes: 2 additions & 5 deletions packages/react-router/lib/hooks.tsx
Expand Up @@ -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;
}

/**
Expand Down

0 comments on commit 39854ce

Please sign in to comment.