Fix route hydration with ssg without early chunk commit (#4654)

* Fix route hydration with ssg without early chunk commit

* fix clobbered port for fullstack spread (merge conflict)

* wait for hydration

---------

Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
Evan AlmloffandJonathan Kelley authored and GitHub committed 2025-10-03 19:59:47 -07:00
1 parent d8a6c265ab
commit d0c4376790
3 files changed
+24 -15

No files matched your search

+18 -12
View File
@@ -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<H> FullstackHistory<H> {
where
H: History,
{
match try_consume_context::<ResolvedRouteContext>() {
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::<RouteEntry>() {
let entry = entry.entry.borrow();
if let Some(entry) = &*entry {
if let Ok(initial_route) = entry.get() {
return initial_route;
}
}
}
self.history.current_route()
}
}
@@ -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");
@@ -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",