diff --git a/src/pages/home.rs b/src/pages/home.rs index 2a8803e..6956456 100644 --- a/src/pages/home.rs +++ b/src/pages/home.rs @@ -51,10 +51,26 @@ pub fn HomePage(page: i32) -> Element { /// /// 通过 `use_server_future` 异步获取当前页文章; /// 加载中显示骨架屏,加载失败显示错误提示,成功则渲染文章卡片与分页。 +/// +/// # 反应式取数 +/// 同 `post_detail.rs`:`current_page` 是普通 `i32` prop,被 `move` 进 +/// `use_server_future` 闭包后成为冻结快照,读取它不建立反应式订阅。因此 +/// `/page/1 → /page/2`(同为 `Route::HomePage` 变体,复用组件实例)这样的 +/// 同变体分页导航无法触发 future 重跑。修复方式:在闭包内通过 +/// `router().current::()` 读取当前 page,建立订阅,路由变化即重跑。 +/// `Home`(`/`)调用时路由变体无 page 字段,兜底用传入的 `current_page`。 #[component] fn HomePosts(current_page: i32) -> Element { - // 调用 server function 获取已发布文章分页数据。 - let posts_res = use_server_future(move || list_published_posts(current_page, POSTS_PER_PAGE))?; + let router = dioxus::router::router(); + + let posts_res = use_server_future(move || { + let page = match router.current::() { + Route::HomePage { page } => page.max(1), + // / 路由(Route::Home)及其它变体:用 prop 兜底。 + _ => current_page, + }; + list_published_posts(page, POSTS_PER_PAGE) + })?; // 将结果映射为更便于本地使用的 (posts, total) 形式。 let posts_data = posts_res.read().as_ref().map(|r| match r { diff --git a/src/pages/tags.rs b/src/pages/tags.rs index ed5c459..e05a29c 100644 --- a/src/pages/tags.rs +++ b/src/pages/tags.rs @@ -120,9 +120,24 @@ pub fn TagDetail(tag: String) -> Element { /// /// 通过 `use_server_future` 调用 `get_posts_by_tag` 获取指定标签下的文章; /// 成功时渲染文章总数与文章卡片。 +/// +/// # 反应式取数 +/// 同 `post_detail.rs` / `home.rs`:`tag` 是普通 `String` prop,被 `move` 进 +/// `use_server_future` 闭包后成为冻结快照,不建立反应式订阅。从标签云点击 +/// 切换标签(`/tags/a → /tags/b`,同为 `Route::TagDetail` 变体,复用组件实例) +/// 时 future 不会重跑。修复:在闭包内通过 `router().current::()` 读取 +/// 当前 tag 建立订阅,路由变化即重跑。 #[component] fn TagDetailContent(tag: String) -> Element { - let posts_res = use_server_future(move || get_posts_by_tag(tag.clone(), None, None))?; + let router = dioxus::router::router(); + + let posts_res = use_server_future(move || { + let current_tag = match router.current::() { + Route::TagDetail { tag } => tag, + _ => tag.clone(), + }; + get_posts_by_tag(current_tag, None, None) + })?; // 将结果映射为 (posts, total) 形式以便渲染。 let posts_data = posts_res.read().as_ref().map(|r| match r {