Skip to content

Commit 6d01688

Browse files
committed
Add changeset
1 parent 2e079d4 commit 6d01688

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

.changeset/calm-crabs-bathe.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 a potential race condition that can occur when rendering a `HydrateFallback` and initial loaders land before the `router.subscribe` call happens in the `RouterProvider` layout effect

packages/react-router/__tests__/dom/data-browser-router-test.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,49 @@ function testDomRouter(
598598
`);
599599
});
600600

601+
it.only("handles race conditions if router initialization completes prior to the layout effect router.subscribe() call", async () => {
602+
let suspenseDfd = createDeferred();
603+
let loaderDfd = createDeferred();
604+
let router = createTestRouter([
605+
{
606+
path: "/",
607+
loader: () =>
608+
loaderDfd.promise.then((d) => {
609+
console.log("returning from loader");
610+
return d;
611+
}),
612+
Component: () => <p>Data:{useLoaderData()}</p>,
613+
HydrateFallback: () => "Hydrate Fallback",
614+
},
615+
]);
616+
expect(router.state.initialized).toBe(false);
617+
618+
function DataLoader() {
619+
console.log("rendering DataLoader");
620+
React.use(suspenseDfd.promise);
621+
console.log(
622+
"DataLoader use() resolved, rendering RouterProvider",
623+
router.state.initialized,
624+
);
625+
return <RouterProvider router={router} />;
626+
}
627+
628+
let { container } = render(
629+
<React.Suspense fallback="Suspense Fallback">
630+
<DataLoader />
631+
</React.Suspense>,
632+
{ reactStrictMode: false },
633+
);
634+
expect(screen.getByText("Suspense Fallback")).toBeDefined();
635+
suspenseDfd.resolve("DATA");
636+
console.log(getHtml(container));
637+
await tick();
638+
console.log(getHtml(container));
639+
loaderDfd.resolve("LOADER");
640+
console.log(getHtml(container));
641+
await waitFor(() => screen.getByText("Data:LOADER"), { timeout: 3000 });
642+
});
643+
601644
it("handles link navigations", async () => {
602645
let router = createTestRouter(
603646
createRoutesFromElements(

0 commit comments

Comments
 (0)