diff --git a/.changeset/young-geese-pay.md b/.changeset/young-geese-pay.md new file mode 100644 index 0000000000..cd03309476 --- /dev/null +++ b/.changeset/young-geese-pay.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +Preserve `clientLoader.hydrate=true` when using `` diff --git a/packages/react-router/__tests__/router/instrumentation-test.ts b/packages/react-router/__tests__/router/instrumentation-test.ts index 54518a8562..52bab8a3b0 100644 --- a/packages/react-router/__tests__/router/instrumentation-test.ts +++ b/packages/react-router/__tests__/router/instrumentation-test.ts @@ -1,6 +1,7 @@ import { createMemoryRouter } from "../../lib/components"; +import { createMemoryHistory } from "../../lib/router/history"; import type { StaticHandlerContext } from "../../lib/router/router"; -import { createStaticHandler } from "../../lib/router/router"; +import { createRouter, createStaticHandler } from "../../lib/router/router"; import { ErrorResponseImpl, data, @@ -112,6 +113,56 @@ describe("instrumentation", () => { }); }); + it("preserves hydrate=true on client side loaders", async () => { + let dfd = createDeferred(); + let spy = jest.fn(); + function loader() { + dfd.resolve(); + return "INDEX*"; + } + loader.hydrate = true; + let router = createRouter({ + history: createMemoryHistory(), + routes: [ + { + id: "index", + index: true, + loader, + }, + ], + hydrationData: { + loaderData: { + index: "INDEX", + }, + }, + unstable_instrumentations: [ + { + route(route) { + route.instrument({ + async loader(loader) { + spy("start"); + await loader(); + spy("end"); + }, + }); + }, + }, + ], + }); + + expect(router.state.initialized).toBe(false); + expect(router.state.loaderData).toEqual({ index: "INDEX" }); + + router.initialize(); + await dfd.promise; + await tick(); + + expect(router.state.initialized).toBe(true); + expect(router.state.loaderData).toEqual({ index: "INDEX*" }); + expect(spy).toHaveBeenCalledWith("start"); + expect(spy).toHaveBeenCalledWith("end"); + }); + it("allows instrumentation of actions", async () => { let spy = jest.fn(); let t = setup({ diff --git a/packages/react-router/lib/router/instrumentation.ts b/packages/react-router/lib/router/instrumentation.ts index 630f485b83..4ba8a16063 100644 --- a/packages/react-router/lib/router/instrumentation.ts +++ b/packages/react-router/lib/router/instrumentation.ts @@ -9,6 +9,7 @@ import type { FormEncType, HTMLFormMethod, LazyRouteObject, + LoaderFunction, LoaderFunctionArgs, MaybePromise, MiddlewareFunction, @@ -218,6 +219,9 @@ export function getRouteInstrumentationUpdates( getHandlerInfo(args[0] as LoaderFunctionArgs | ActionFunctionArgs), ); if (instrumented) { + if (key === "loader" && original.hydrate === true) { + (instrumented as LoaderFunction).hydrate = true; + } // @ts-expect-error instrumented[UninstrumentedSymbol] = original; updates[key] = instrumented;