From e50385879bd418d552e8bc93c04afdbf453cdd4b Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Tue, 9 Sep 2025 21:39:19 -0700 Subject: [PATCH] Fix Router navigation state handling The changes improve state handling during client-side navigation by: - Using correct function updates with setAppState - Preserving abort controller on updates - Adding proper cache ID comparison - Moving router instance to constants --- packages/bun-framework-react/client.tsx | 9 +-------- packages/bun-framework-react/client/router.ts | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/packages/bun-framework-react/client.tsx b/packages/bun-framework-react/client.tsx index 9bb4465ee8..6c867bebc9 100644 --- a/packages/bun-framework-react/client.tsx +++ b/packages/bun-framework-react/client.tsx @@ -1,10 +1,8 @@ import { onServerSideReload } from "bun:app/client"; import { hydrateRoot } from "react-dom/client"; import { initialRscPayloadThen } from "./client/app.ts"; +import { router } from "./client/constants.ts"; import { Root } from "./client/root.tsx"; -import { Router } from "./client/router.ts"; - -const router = new Router(); hydrateRoot(document, , { onUncaughtError(e) { @@ -50,13 +48,8 @@ const firstPageId = Date.now(); } } -// Client side navigation is implemented by updating the app's `useState` with a -// new RSC payload promise. Callers of `navigate` are expected to manage history -// state. A navigation id is used - window.addEventListener("popstate", async event => { const state = typeof event.state === "number" ? event.state : undefined; - await router.navigate(location.href, state); }); diff --git a/packages/bun-framework-react/client/router.ts b/packages/bun-framework-react/client/router.ts index 4a4eaa4a17..f06237a9fd 100644 --- a/packages/bun-framework-react/client/router.ts +++ b/packages/bun-framework-react/client/router.ts @@ -109,7 +109,7 @@ export class Router { // Save this promise so that pressing the back button in the browser navigates // to the same instance of the old page, instead of re-fetching it. - if (cacheId) { + if (cacheId !== undefined) { this.cachedPages.set(cacheId, { css: [...this.css.getList()], element: p, @@ -124,21 +124,22 @@ export class Router { } // Tell react about the new page promise - if (document.startViewTransition as unknown) { + if (document.startViewTransition) { document.startViewTransition(() => { flushSync(() => { - if (thisNavigationId === this.lastNavigationId) - setAppState({ + if (thisNavigationId === this.lastNavigationId) { + setAppState(old => ({ rsc: p, - abortOnRender: olderController ?? undefined, - }); + abortOnRender: olderController ?? old.abortOnRender, + })); + } }); }); } else { - setAppState({ + setAppState(old => ({ rsc: p, - abortOnRender: olderController ?? undefined, - }); + abortOnRender: olderController ?? old.abortOnRender, + })); } } }