fix(hooks): 修复 wasm32 target 编译失败

之前验证只跑了 server target(cargo build --all-features),漏掉 wasm32
前端 target,导致三类错误未被捕获:

1. event_listener.rs wasm 分支缺 use dioxus::prelude::*:
   use_hook/use_effect/use_drop 来自 prelude,之前重写时误删。补回。

2. event_listener.rs use_effect 闭包 move 冲突(E0507/E0310):
   use_effect 回调是 FnMut,但 acquire 是 FnOnce、handler 要 move 进事件
   闭包。用 Option::take 模式包裹,首次运行消费,避免重复 move。同时给
   A 加上 'static 约束。

3. query.rs items/total/footer.rs sync_visible 缺 mut:
   wasm 分支的 .set() 调用需要 mut 绑定。之前为消 server target 的
   unused_mut 警告误删,改用 cfg_attr 在非 wasm 时压制警告。

教训:fullstack 项目必须同时验证 wasm32 与 server 两个 target,单一
target 通过不代表整体可用。
This commit is contained in:
xfy 2026-07-02 16:43:15 +08:00
parent 291189fb77
commit 2b6b2ca9e4
3 changed files with 15 additions and 6 deletions

View File

@ -21,7 +21,7 @@ pub fn Footer() -> Element {
// 根据 window 当前滚动位置同步 visible注册监听后立即调用一次避免首屏漏判
// 滚动事件回调里也复用同一份判断逻辑。
let sync_visible = move || {
let mut sync_visible = move || {
#[cfg(target_arch = "wasm32")]
{
if let Some(w) = web_sys::window() {

View File

@ -30,12 +30,13 @@
/// );
/// ```
#[cfg(target_arch = "wasm32")]
pub fn use_event_listener<T, A, F>(acquire: A, event: &'static str, mut handler: F)
pub fn use_event_listener<T, A, F>(acquire: A, event: &'static str, handler: F)
where
T: AsRef<web_sys::EventTarget> + Clone + 'static,
A: FnOnce() -> Option<T>,
A: FnOnce() -> Option<T> + 'static,
F: FnMut() + 'static,
{
use dioxus::prelude::*;
use std::cell::RefCell;
use std::rc::Rc;
@ -45,7 +46,14 @@ where
use_hook(|| Rc::new(RefCell::new(None)));
let state_for_drop = state.clone();
// use_effect 的回调是 FnMut可能多次运行但 acquire 是 FnOnce、handler 要
// move 进事件闭包。用 Option 包裹后 take(),首次运行消费掉,避免重复 move。
let mut acquire = Some(acquire);
let mut handler = Some(handler);
use_effect(move || {
let Some(acquire) = acquire.take() else { return };
let Some(mut handler) = handler.take() else { return };
let Some(target) = acquire() else { return };
let target_clone = target.clone();
let closure = wasm_bindgen::prelude::Closure::wrap(Box::new(move || {
@ -77,7 +85,7 @@ where
pub fn use_event_listener<T, A, F>(acquire: A, event: &'static str, handler: F)
where
T: Clone + 'static,
A: FnOnce() -> Option<T>,
A: FnOnce() -> Option<T> + 'static,
F: FnMut() + 'static,
{
// SSR 无 DOM空实现。

View File

@ -46,6 +46,7 @@ pub struct PaginatedState<T> {
/// },
/// );
/// ```
#[cfg_attr(not(target_arch = "wasm32"), allow(unused_mut))]
#[allow(unused_variables)]
pub fn use_paginated<T, P, F, Fut, E>(
page: P,
@ -60,8 +61,8 @@ where
E: std::fmt::Display + 'static,
{
let mut loading = use_signal(|| true);
let items = use_signal(Vec::new);
let total = use_signal(|| 0_i64);
let mut items = use_signal(Vec::new);
let mut total = use_signal(|| 0_i64);
let mut error: Signal<Option<String>> = use_signal(|| None);
use_effect(move || {