Fix router state after client side navigation (#4383)
* Fix router state after client side navigation * add client side navigation to the fullstack routing spec * fix playwright test
This commit is contained in:
1 parent
ddc94cf44c
commit
b252528722
4 files changed
+53
-5
No files matched your search
@@ -2,10 +2,8 @@
|
||||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use dioxus_core::{
|
||||
prelude::{generation, queue_effect},
|
||||
schedule_update,
|
||||
};
|
||||
use dioxus_core::{prelude::queue_effect, schedule_update};
|
||||
use dioxus_fullstack_protocol::is_hydrating;
|
||||
use dioxus_history::History;
|
||||
|
||||
// If we are currently in a scope and this is the first run then queue a rerender
|
||||
@@ -14,7 +12,7 @@ fn match_hydration<O>(
|
||||
during_hydration: impl FnOnce() -> O,
|
||||
after_hydration: impl FnOnce() -> O,
|
||||
) -> O {
|
||||
if generation() == 0 {
|
||||
if is_hydrating() {
|
||||
let update = schedule_update();
|
||||
queue_effect(move || update());
|
||||
during_hydration()
|
||||
|
||||
@@ -144,6 +144,19 @@ impl<T> SerializeContextEntry<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the client is currently rendering a component for hydration. Always returns true on the server.
|
||||
pub fn is_hydrating() -> bool {
|
||||
#[cfg(feature = "web")]
|
||||
{
|
||||
// On the client, we can check if the context is set
|
||||
CONTEXT.with(|context| context.borrow().is_some())
|
||||
}
|
||||
#[cfg(not(feature = "web"))]
|
||||
{
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Get or insert the current serialize context. On the client, the hydration context this returns
|
||||
/// will always return `TakeDataError::DataNotAvailable` if hydration of the current chunk is finished.
|
||||
pub fn serialize_context() -> HydrationContext {
|
||||
|
||||
@@ -51,3 +51,33 @@ test("unknown route", async ({ request }) => {
|
||||
|
||||
expect(response.status()).toBe(404);
|
||||
});
|
||||
|
||||
// Clicking the link on the home page should navigate to the blog route
|
||||
test("click blog link", async ({ page }) => {
|
||||
await page.goto("http://localhost:8888");
|
||||
|
||||
// Click the link to the blog route
|
||||
await page.locator('a').click();
|
||||
|
||||
// Wait for navigation to complete
|
||||
await page.waitForURL("http://localhost:8888/blog/1/");
|
||||
|
||||
// Check that the blog page is displayed
|
||||
const text = await page.textContent("body");
|
||||
expect(text).toContain("id: 1");
|
||||
});
|
||||
|
||||
// Clicking the link on the blog page should navigate back to the home route
|
||||
test("click home link from blog", async ({ page }) => {
|
||||
await page.goto("http://localhost:8888/blog/1");
|
||||
|
||||
// Click the link to the home route
|
||||
await page.locator('a').click();
|
||||
|
||||
// Wait for navigation to complete
|
||||
await page.waitForURL("http://localhost:8888");
|
||||
|
||||
// Check that the home page is displayed
|
||||
const text = await page.textContent("body");
|
||||
expect(text).toContain("Home");
|
||||
});
|
||||
@@ -36,6 +36,9 @@ enum Route {
|
||||
|
||||
#[component]
|
||||
fn Blog(id: i32) -> Element {
|
||||
let route: Route = use_route();
|
||||
assert_eq!(route, Route::Blog { id });
|
||||
|
||||
rsx! {
|
||||
Link { to: Route::Home {}, "Go home" }
|
||||
"id: {id}"
|
||||
@@ -51,8 +54,12 @@ fn ThrowsError() -> Element {
|
||||
|
||||
#[component]
|
||||
fn Home() -> Element {
|
||||
let route: Route = use_route();
|
||||
assert_eq!(route, Route::Home);
|
||||
|
||||
rsx! {
|
||||
"Home"
|
||||
Link { to: Route::Blog { id: 1 }, "Go to blog 1" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user