Skip to content

Commit 54db9b4

Browse files
authored
ci: add tests for useRouteLoaderData with a missing routeId (#8967)
1 parent 5ec32d2 commit 54db9b4

File tree

2 files changed

+137
-107
lines changed

2 files changed

+137
-107
lines changed

packages/react-router/__tests__/DataMemoryRouter-test.tsx

Lines changed: 134 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ describe("<DataMemoryRouter>", () => {
520520
`);
521521
});
522522

523-
it("provides useMatches and useRouteLoaderData", async () => {
523+
it("provides useMatches", async () => {
524524
let spy = jest.fn();
525525

526526
render(
@@ -542,127 +542,157 @@ describe("<DataMemoryRouter>", () => {
542542
);
543543

544544
function Layout() {
545-
spy({
546-
component: "Layout",
547-
useMatches: useMatches(),
548-
useRouteLoaderData: useRouteLoaderData("0"),
549-
});
545+
spy("Layout", useMatches());
550546
return (
551-
<div>
547+
<>
552548
<MemoryNavigate to="/bar">Link to Bar</MemoryNavigate>
553549
<Outlet />
554-
</div>
550+
</>
555551
);
556552
}
557553

558554
function Foo() {
559-
spy({
560-
component: "Foo",
561-
useMatches: useMatches(),
562-
useRouteLoaderData: useRouteLoaderData("0-0"),
563-
});
555+
spy("Foo", useMatches());
564556
return <h1>Foo</h1>;
565557
}
558+
566559
function Bar() {
567-
spy({
568-
component: "Bar",
569-
useMatches: useMatches(),
570-
useRouteLoaderData: useRouteLoaderData("0-1"),
571-
});
560+
spy("Bar", useMatches());
572561
return <h1>Bar</h1>;
573562
}
574563

575-
expect(spy.mock.calls[0]).toMatchInlineSnapshot(`
576-
Array [
577-
Object {
578-
"component": "Layout",
579-
"useMatches": Array [
580-
Object {
581-
"data": undefined,
582-
"handle": undefined,
583-
"id": "0",
584-
"params": Object {},
585-
"pathname": "/",
586-
},
587-
],
588-
"useRouteLoaderData": undefined,
589-
},
590-
]
591-
`);
592-
expect(spy.mock.calls.length).toBe(1);
564+
expect(spy).toHaveBeenCalledWith("Layout", [
565+
{
566+
data: undefined,
567+
handle: undefined,
568+
id: "0",
569+
params: {},
570+
pathname: "/",
571+
},
572+
]);
573+
574+
spy.mockClear();
593575
fireEvent.click(screen.getByText("Link to Bar"));
594-
expect(spy.mock.calls[1]).toMatchInlineSnapshot(`
595-
Array [
596-
Object {
597-
"component": "Layout",
598-
"useMatches": Array [
599-
Object {
600-
"data": undefined,
601-
"handle": undefined,
602-
"id": "0",
603-
"params": Object {},
604-
"pathname": "/",
605-
},
606-
],
607-
"useRouteLoaderData": undefined,
608-
},
609-
]
610-
`);
611-
expect(spy.mock.calls.length).toBe(2);
576+
expect(spy).toHaveBeenCalledWith("Layout", [
577+
{
578+
data: undefined,
579+
handle: undefined,
580+
id: "0",
581+
params: {},
582+
pathname: "/",
583+
},
584+
]);
585+
586+
spy.mockClear();
612587
await waitFor(() => screen.getByText("Bar"));
613-
expect(spy.mock.calls[2]).toMatchInlineSnapshot(`
614-
Array [
615-
Object {
616-
"component": "Layout",
617-
"useMatches": Array [
618-
Object {
619-
"data": undefined,
620-
"handle": undefined,
621-
"id": "0",
622-
"params": Object {},
623-
"pathname": "/",
624-
},
625-
Object {
626-
"data": "BAR LOADER",
627-
"handle": Object {
628-
"key": "value",
629-
},
630-
"id": "0-1",
631-
"params": Object {},
632-
"pathname": "/bar",
633-
},
634-
],
635-
"useRouteLoaderData": undefined,
588+
expect(spy).toHaveBeenCalledWith("Layout", [
589+
{
590+
data: undefined,
591+
handle: undefined,
592+
id: "0",
593+
params: {},
594+
pathname: "/",
595+
},
596+
{
597+
data: "BAR LOADER",
598+
handle: {
599+
key: "value",
636600
},
637-
]
601+
id: "0-1",
602+
params: {},
603+
pathname: "/bar",
604+
},
605+
]);
606+
});
607+
608+
it("provides useRouteLoaderData", async () => {
609+
let spy = jest.fn();
610+
611+
let { container } = render(
612+
<DataMemoryRouter
613+
initialEntries={["/foo"]}
614+
hydrationData={{
615+
loaderData: {
616+
layout: null,
617+
foo: "FOO",
618+
},
619+
}}
620+
>
621+
<Route id="layout" path="/" element={<Layout />}>
622+
<Route
623+
id="foo"
624+
path="foo"
625+
loader={async () => "FOO2"}
626+
element={<h2>Foo</h2>}
627+
/>
628+
<Route id="bar" path="bar" element={<Outlet />}>
629+
<Route
630+
id="child"
631+
path="child"
632+
loader={async () => "CHILD"}
633+
element={<h2>Child</h2>}
634+
/>
635+
</Route>
636+
</Route>
637+
</DataMemoryRouter>
638+
);
639+
640+
function Layout() {
641+
spy({
642+
layout: useRouteLoaderData("layout"),
643+
foo: useRouteLoaderData("foo"),
644+
bar: useRouteLoaderData("bar"),
645+
child: useRouteLoaderData("child"),
646+
});
647+
return (
648+
<>
649+
<MemoryNavigate to="/bar/child">Link to Child</MemoryNavigate>
650+
<Outlet />
651+
</>
652+
);
653+
}
654+
655+
expect(spy).toHaveBeenCalledWith({
656+
layout: null,
657+
foo: "FOO",
658+
bar: undefined,
659+
child: undefined,
660+
});
661+
expect(getHtml(container)).toMatchInlineSnapshot(`
662+
"<div>
663+
<a
664+
href=\\"/bar/child\\"
665+
>
666+
Link to Child
667+
</a>
668+
<h2>
669+
Foo
670+
</h2>
671+
</div>"
638672
`);
639-
expect(spy.mock.calls[3]).toMatchInlineSnapshot(`
640-
Array [
641-
Object {
642-
"component": "Bar",
643-
"useMatches": Array [
644-
Object {
645-
"data": undefined,
646-
"handle": undefined,
647-
"id": "0",
648-
"params": Object {},
649-
"pathname": "/",
650-
},
651-
Object {
652-
"data": "BAR LOADER",
653-
"handle": Object {
654-
"key": "value",
655-
},
656-
"id": "0-1",
657-
"params": Object {},
658-
"pathname": "/bar",
659-
},
660-
],
661-
"useRouteLoaderData": "BAR LOADER",
662-
},
663-
]
673+
674+
spy.mockClear();
675+
fireEvent.click(screen.getByText("Link to Child"));
676+
await new Promise((r) => setImmediate(r));
677+
678+
expect(getHtml(container)).toMatchInlineSnapshot(`
679+
"<div>
680+
<a
681+
href=\\"/bar/child\\"
682+
>
683+
Link to Child
684+
</a>
685+
<h2>
686+
Child
687+
</h2>
688+
</div>"
664689
`);
665-
expect(spy.mock.calls.length).toBe(4);
690+
expect(spy).toHaveBeenCalledWith({
691+
layout: null,
692+
foo: undefined,
693+
bar: undefined,
694+
child: "CHILD",
695+
});
666696
});
667697

668698
it("reloads data using useRevalidate", async () => {

packages/react-router/lib/hooks.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,15 +637,15 @@ export function useLoaderData() {
637637
`useLoaderData can only be used on routes that contain a unique "id"`
638638
);
639639

640-
return state.loaderData?.[thisRoute.route.id];
640+
return state.loaderData[thisRoute.route.id];
641641
}
642642

643643
/**
644644
* Returns the loaderData for the given routeId
645645
*/
646-
export function useRouteLoaderData(routeId: string): any {
646+
export function useRouteLoaderData(routeId: string): any | undefined {
647647
let state = useDataRouterState(DataRouterHook.UseRouteLoaderData);
648-
return state.loaderData?.[routeId];
648+
return state.loaderData[routeId];
649649
}
650650

651651
/**

0 commit comments

Comments
 (0)