diff --git a/packages/fullstack-core/src/history.rs b/packages/fullstack-core/src/history.rs index 8e15c1617..77398eb19 100644 --- a/packages/fullstack-core/src/history.rs +++ b/packages/fullstack-core/src/history.rs @@ -33,11 +33,10 @@ pub(crate) fn finalize_route() { return; }; - let entry = entry - .entry - .borrow_mut() - .take() - .expect("Failed to get initial route from hydration context"); + let Some(entry) = entry.entry.borrow_mut().take() else { + // If it was already taken, then just return. This can happen if commit_initial_chunk is called twice + return; + }; if cfg!(feature = "server") { let history = history(); @@ -45,12 +44,10 @@ pub(crate) fn finalize_route() { entry.insert(&route, std::panic::Location::caller()); provide_context(ResolvedRouteContext { route }); } else if cfg!(feature = "web") { - let initial_route = entry + let route = entry .get() .expect("Failed to get initial route from hydration context"); - provide_context(ResolvedRouteContext { - route: initial_route, - }); + provide_context(ResolvedRouteContext { route }); } } @@ -86,10 +83,19 @@ impl FullstackHistory { where H: History, { - match try_consume_context::() { - Some(context) => context.route, - None => self.history.current_route(), + // If the route hydration entry is set, use that instead of the histories current route + // for better hydration behavior. The client may be rendering from a ssg route that was + // rendered at a different url + if let Some(entry) = try_consume_context::() { + let entry = entry.entry.borrow(); + if let Some(entry) = &*entry { + if let Ok(initial_route) = entry.get() { + return initial_route; + } + } } + + self.history.current_route() } } diff --git a/packages/playwright-tests/fullstack-spread.spec.js b/packages/playwright-tests/fullstack-spread.spec.js index 142438b66..08be19c97 100644 --- a/packages/playwright-tests/fullstack-spread.spec.js +++ b/packages/playwright-tests/fullstack-spread.spec.js @@ -2,11 +2,14 @@ const { test, expect } = require("@playwright/test"); test("spread attributes hydrate", async ({ page }) => { - await page.goto("http://localhost:7979"); + await page.goto("http://localhost:7980"); + + await page.waitForTimeout(2000); // wait for hydration // Expect the page to contain the button const counter = page.locator("#counter"); await expect(counter).toHaveText("Count: 0"); + // Clicking on the button should increment the count await counter.click(); await expect(counter).toHaveText("Count: 1"); diff --git a/packages/playwright-tests/playwright.config.js b/packages/playwright-tests/playwright.config.js index 17ebf4c71..2f1c95723 100644 --- a/packages/playwright-tests/playwright.config.js +++ b/packages/playwright-tests/playwright.config.js @@ -111,8 +111,8 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "fullstack-spread"), command: - 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --web --addr "127.0.0.1" --port 7979', - port: 7979, + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --web --addr "127.0.0.1" --port 7980', + port: 7980, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, stdout: "pipe",