Skip to content

Commit 1954af6

Browse files
authored
Preserve hydrate property on client loaders during instrumentation (#14674)
1 parent 915694e commit 1954af6

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

.changeset/young-geese-pay.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+
Preserve `clientLoader.hydrate=true` when using `<HydratedRouter unstable_instrumentations>`

packages/react-router/__tests__/router/instrumentation-test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createMemoryRouter } from "../../lib/components";
2+
import { createMemoryHistory } from "../../lib/router/history";
23
import type { StaticHandlerContext } from "../../lib/router/router";
3-
import { createStaticHandler } from "../../lib/router/router";
4+
import { createRouter, createStaticHandler } from "../../lib/router/router";
45
import {
56
ErrorResponseImpl,
67
data,
@@ -112,6 +113,56 @@ describe("instrumentation", () => {
112113
});
113114
});
114115

116+
it("preserves hydrate=true on client side loaders", async () => {
117+
let dfd = createDeferred();
118+
let spy = jest.fn();
119+
function loader() {
120+
dfd.resolve();
121+
return "INDEX*";
122+
}
123+
loader.hydrate = true;
124+
let router = createRouter({
125+
history: createMemoryHistory(),
126+
routes: [
127+
{
128+
id: "index",
129+
index: true,
130+
loader,
131+
},
132+
],
133+
hydrationData: {
134+
loaderData: {
135+
index: "INDEX",
136+
},
137+
},
138+
unstable_instrumentations: [
139+
{
140+
route(route) {
141+
route.instrument({
142+
async loader(loader) {
143+
spy("start");
144+
await loader();
145+
spy("end");
146+
},
147+
});
148+
},
149+
},
150+
],
151+
});
152+
153+
expect(router.state.initialized).toBe(false);
154+
expect(router.state.loaderData).toEqual({ index: "INDEX" });
155+
156+
router.initialize();
157+
await dfd.promise;
158+
await tick();
159+
160+
expect(router.state.initialized).toBe(true);
161+
expect(router.state.loaderData).toEqual({ index: "INDEX*" });
162+
expect(spy).toHaveBeenCalledWith("start");
163+
expect(spy).toHaveBeenCalledWith("end");
164+
});
165+
115166
it("allows instrumentation of actions", async () => {
116167
let spy = jest.fn();
117168
let t = setup({

packages/react-router/lib/router/instrumentation.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
FormEncType,
1010
HTMLFormMethod,
1111
LazyRouteObject,
12+
LoaderFunction,
1213
LoaderFunctionArgs,
1314
MaybePromise,
1415
MiddlewareFunction,
@@ -218,6 +219,9 @@ export function getRouteInstrumentationUpdates(
218219
getHandlerInfo(args[0] as LoaderFunctionArgs | ActionFunctionArgs),
219220
);
220221
if (instrumented) {
222+
if (key === "loader" && original.hydrate === true) {
223+
(instrumented as LoaderFunction).hydrate = true;
224+
}
221225
// @ts-expect-error
222226
instrumented[UninstrumentedSymbol] = original;
223227
updates[key] = instrumented;

0 commit comments

Comments
 (0)