Skip to content

Commit 48b29ba

Browse files
authored
Fix a partial hydration bug for routes with no loaders (#11325)
1 parent 05588d2 commit 48b29ba

File tree

3 files changed

+57
-5
lines changed

3 files changed

+57
-5
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/router": patch
3+
---
4+
5+
Fix a `future.v7_partialHydration` bug that would consider the router uninitialized if a route did not have a loader

packages/router/__tests__/route-fallback-test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,4 +515,45 @@ describe("future.v7_partialHydration", () => {
515515
consoleWarnSpy.mockReset();
516516
});
517517
});
518+
519+
it("does not kick off initial data load for routes that don't have loaders", async () => {
520+
let consoleWarnSpy = jest
521+
.spyOn(console, "warn")
522+
.mockImplementation(() => {});
523+
let parentDfd = createDeferred();
524+
let parentSpy = jest.fn(() => parentDfd.promise);
525+
let router = createRouter({
526+
history: createMemoryHistory({ initialEntries: ["/child"] }),
527+
routes: [
528+
{
529+
path: "/",
530+
loader: parentSpy,
531+
children: [
532+
{
533+
path: "child",
534+
},
535+
],
536+
},
537+
],
538+
future: {
539+
v7_partialHydration: true,
540+
},
541+
hydrationData: {
542+
loaderData: {
543+
"0": "PARENT DATA",
544+
},
545+
},
546+
});
547+
expect(router.state).toMatchObject({
548+
// already initialized so calling initialize() won't kick off loaders
549+
initialized: true,
550+
navigation: IDLE_NAVIGATION,
551+
loaderData: {
552+
"0": "PARENT DATA",
553+
},
554+
});
555+
556+
router.dispose();
557+
consoleWarnSpy.mockReset();
558+
});
518559
});

packages/router/router.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -833,11 +833,17 @@ export function createRouter(init: RouterInit): Router {
833833
// were marked for explicit hydration
834834
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
835835
let errors = init.hydrationData ? init.hydrationData.errors : null;
836-
let isRouteInitialized = (m: AgnosticDataRouteMatch) =>
837-
m.route.loader &&
838-
m.route.loader.hydrate !== true &&
839-
((loaderData && loaderData[m.route.id] !== undefined) ||
840-
(errors && errors[m.route.id] !== undefined));
836+
let isRouteInitialized = (m: AgnosticDataRouteMatch) => {
837+
// No loader, nothing to initialize
838+
if (!m.route.loader) return true;
839+
// Explicitly opting-in to running on hydration
840+
if (m.route.loader.hydrate === true) return false;
841+
// Otherwise, initialized if hydrated with data or an error
842+
return (
843+
(loaderData && loaderData[m.route.id] !== undefined) ||
844+
(errors && errors[m.route.id] !== undefined)
845+
);
846+
};
841847

842848
// If errors exist, don't consider routes below the boundary
843849
if (errors) {

0 commit comments

Comments
 (0)