Skip to content

Commit

Permalink
Fix a partial hydration bug for routes with no loaders (#11325)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Mar 5, 2024
1 parent 05588d2 commit 48b29ba
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/partial-hydration-no-loader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/router": patch
---

Fix a `future.v7_partialHydration` bug that would consider the router uninitialized if a route did not have a loader
41 changes: 41 additions & 0 deletions packages/router/__tests__/route-fallback-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,4 +515,45 @@ describe("future.v7_partialHydration", () => {
consoleWarnSpy.mockReset();
});
});

it("does not kick off initial data load for routes that don't have loaders", async () => {
let consoleWarnSpy = jest
.spyOn(console, "warn")
.mockImplementation(() => {});
let parentDfd = createDeferred();
let parentSpy = jest.fn(() => parentDfd.promise);
let router = createRouter({
history: createMemoryHistory({ initialEntries: ["/child"] }),
routes: [
{
path: "/",
loader: parentSpy,
children: [
{
path: "child",
},
],
},
],
future: {
v7_partialHydration: true,
},
hydrationData: {
loaderData: {
"0": "PARENT DATA",
},
},
});
expect(router.state).toMatchObject({
// already initialized so calling initialize() won't kick off loaders
initialized: true,
navigation: IDLE_NAVIGATION,
loaderData: {
"0": "PARENT DATA",
},
});

router.dispose();
consoleWarnSpy.mockReset();
});
});
16 changes: 11 additions & 5 deletions packages/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -833,11 +833,17 @@ export function createRouter(init: RouterInit): Router {
// were marked for explicit hydration
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
let errors = init.hydrationData ? init.hydrationData.errors : null;
let isRouteInitialized = (m: AgnosticDataRouteMatch) =>
m.route.loader &&
m.route.loader.hydrate !== true &&
((loaderData && loaderData[m.route.id] !== undefined) ||
(errors && errors[m.route.id] !== undefined));
let isRouteInitialized = (m: AgnosticDataRouteMatch) => {
// No loader, nothing to initialize
if (!m.route.loader) return true;
// Explicitly opting-in to running on hydration
if (m.route.loader.hydrate === true) return false;
// Otherwise, initialized if hydrated with data or an error
return (
(loaderData && loaderData[m.route.id] !== undefined) ||
(errors && errors[m.route.id] !== undefined)
);
};

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

0 comments on commit 48b29ba

Please sign in to comment.