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 std::cell::OnceCell;
|
||||||
|
|
||||||
use dioxus_core::{
|
use dioxus_core::{prelude::queue_effect, schedule_update};
|
||||||
prelude::{generation, queue_effect},
|
use dioxus_fullstack_protocol::is_hydrating;
|
||||||
schedule_update,
|
|
||||||
};
|
|
||||||
use dioxus_history::History;
|
use dioxus_history::History;
|
||||||
|
|
||||||
// If we are currently in a scope and this is the first run then queue a rerender
|
// 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,
|
during_hydration: impl FnOnce() -> O,
|
||||||
after_hydration: impl FnOnce() -> O,
|
after_hydration: impl FnOnce() -> O,
|
||||||
) -> O {
|
) -> O {
|
||||||
if generation() == 0 {
|
if is_hydrating() {
|
||||||
let update = schedule_update();
|
let update = schedule_update();
|
||||||
queue_effect(move || update());
|
queue_effect(move || update());
|
||||||
during_hydration()
|
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
|
/// 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.
|
/// will always return `TakeDataError::DataNotAvailable` if hydration of the current chunk is finished.
|
||||||
pub fn serialize_context() -> HydrationContext {
|
pub fn serialize_context() -> HydrationContext {
|
||||||
|
|||||||
@@ -51,3 +51,33 @@ test("unknown route", async ({ request }) => {
|
|||||||
|
|
||||||
expect(response.status()).toBe(404);
|
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]
|
#[component]
|
||||||
fn Blog(id: i32) -> Element {
|
fn Blog(id: i32) -> Element {
|
||||||
|
let route: Route = use_route();
|
||||||
|
assert_eq!(route, Route::Blog { id });
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
Link { to: Route::Home {}, "Go home" }
|
Link { to: Route::Home {}, "Go home" }
|
||||||
"id: {id}"
|
"id: {id}"
|
||||||
@@ -51,8 +54,12 @@ fn ThrowsError() -> Element {
|
|||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Home() -> Element {
|
fn Home() -> Element {
|
||||||
|
let route: Route = use_route();
|
||||||
|
assert_eq!(route, Route::Home);
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
"Home"
|
"Home"
|
||||||
|
Link { to: Route::Blog { id: 1 }, "Go to blog 1" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user