Skip to content

Commit e0c207d

Browse files
authored
Fix clientLoader hydrate behavior when ancestor route is hydrating a loader (#14835)
1 parent d8ffb2d commit e0c207d

File tree

3 files changed

+82
-11
lines changed

3 files changed

+82
-11
lines changed

.changeset/cold-schools-relate.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+
Fix clientLoader.hydrate when an ancestor route is also hydrating a clientLoader

packages/react-router/__tests__/dom/partial-hydration-test.tsx

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ describe("Partial Hydration Behavior", () => {
6666
},
6767
],
6868
{
69-
future: {
70-
v7_partialHydration: true,
71-
},
7269
patchRoutesOnNavigation({ path, patch }) {
7370
if (path === "/parent/child") {
7471
patch("parent", [
@@ -155,9 +152,6 @@ describe("Partial Hydration Behavior", () => {
155152
},
156153
],
157154
{
158-
future: {
159-
v7_partialHydration: true,
160-
},
161155
patchRoutesOnNavigation({ path, patch }) {
162156
if (path === "/parent/child") {
163157
patch("parent", [
@@ -248,9 +242,6 @@ describe("Partial Hydration Behavior", () => {
248242
},
249243
],
250244
{
251-
future: {
252-
v7_partialHydration: true,
253-
},
254245
async patchRoutesOnNavigation({ path, patch }) {
255246
await patchDfd.promise;
256247
if (path === "/parent/child") {
@@ -853,4 +844,76 @@ function testPartialHydration(
853844
expect(rootSpy).toHaveBeenCalledTimes(1);
854845
expect(indexSpy).not.toHaveBeenCalled();
855846
});
847+
848+
it("renders child fallback when ancestor route has hydration data and a hydrating loader", async () => {
849+
let rootDfd = createDeferred();
850+
let rootLoader: LoaderFunction = () => rootDfd.promise;
851+
rootLoader.hydrate = true;
852+
let indexDfd = createDeferred();
853+
let indexLoader: LoaderFunction = () => indexDfd.promise;
854+
indexLoader.hydrate = true;
855+
let router = createTestRouter(
856+
[
857+
{
858+
id: "root",
859+
path: "/",
860+
loader: rootLoader,
861+
Component() {
862+
let data = useLoaderData() as string;
863+
return (
864+
<>
865+
<h1>{`Home - ${data}`}</h1>
866+
<Outlet />
867+
</>
868+
);
869+
},
870+
children: [
871+
{
872+
id: "index",
873+
index: true,
874+
loader: indexLoader,
875+
HydrateFallback: () => <p>Index Loading...</p>,
876+
Component() {
877+
let data = useLoaderData() as string;
878+
return <h2>{`Index - ${data}`}</h2>;
879+
},
880+
},
881+
],
882+
},
883+
],
884+
{
885+
hydrationData: {
886+
loaderData: {
887+
root: "HYDRATED ROOT",
888+
},
889+
},
890+
},
891+
);
892+
let { container } = render(<RouterProvider router={router} />);
893+
894+
expect(getHtml(container)).toMatchInlineSnapshot(`
895+
"<div>
896+
<h1>
897+
Home - HYDRATED ROOT
898+
</h1>
899+
<p>
900+
Index Loading...
901+
</p>
902+
</div>"
903+
`);
904+
905+
rootDfd.resolve("ROOT UPDATED");
906+
indexDfd.resolve("INDEX UPDATED");
907+
await waitFor(() => screen.getByText(/INDEX UPDATED/));
908+
expect(getHtml(container)).toMatchInlineSnapshot(`
909+
"<div>
910+
<h1>
911+
Home - ROOT UPDATED
912+
</h1>
913+
<h2>
914+
Index - INDEX UPDATED
915+
</h2>
916+
</div>"
917+
`);
918+
});
856919
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,11 +1024,14 @@ export function createRouter(init: RouterInit): Router {
10241024
}
10251025

10261026
// Toggle renderFallback based on per-route values
1027+
// Using a `.forEach` is important instead of something like an `.every`
1028+
// here because we need to evaluate renderFallback for all matches
10271029
renderFallback = false;
1028-
initialized = relevantMatches.every((m) => {
1030+
initialized = true;
1031+
relevantMatches.forEach((m) => {
10291032
let status = getRouteHydrationStatus(m.route, loaderData, errors);
10301033
renderFallback = renderFallback || status.renderFallback;
1031-
return !status.shouldLoad;
1034+
initialized = initialized && !status.shouldLoad;
10321035
});
10331036
}
10341037
}

0 commit comments

Comments
 (0)